Line data Source code
1 : #ifndef AWS_COMMON_MATH_GCC_OVERFLOW_INL
2 : #define AWS_COMMON_MATH_GCC_OVERFLOW_INL
3 :
4 : /**
5 : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 : * SPDX-License-Identifier: Apache-2.0.
7 : */
8 :
9 : /*
10 : * This header is already included, but include it again to make editor
11 : * highlighting happier.
12 : */
13 : #include <aws/common/common.h>
14 : #include <aws/common/math.h>
15 :
16 : AWS_EXTERN_C_BEGIN
17 : /**
18 : * Multiplies a * b. If the result overflows, returns 2^64 - 1.
19 : */
20 29431 : AWS_STATIC_IMPL uint64_t aws_mul_u64_saturating(uint64_t a, uint64_t b) {
21 29431 : uint64_t res;
22 29431 :
23 29431 : if (__builtin_mul_overflow(a, b, &res)) {
24 11589 : res = UINT64_MAX;
25 11589 : }
26 29431 :
27 29431 : return res;
28 29431 : }
29 :
30 : /**
31 : * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies
32 : * a * b, returns the result in *r, and returns AWS_OP_SUCCESS.
33 : */
34 8356339 : AWS_STATIC_IMPL int aws_mul_u64_checked(uint64_t a, uint64_t b, uint64_t *r) {
35 8356339 : if (__builtin_mul_overflow(a, b, r)) {
36 29278 : return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
37 29278 : }
38 8327061 : return AWS_OP_SUCCESS;
39 8327061 : }
40 :
41 : /**
42 : * Multiplies a * b. If the result overflows, returns 2^32 - 1.
43 : */
44 13834 : AWS_STATIC_IMPL uint32_t aws_mul_u32_saturating(uint32_t a, uint32_t b) {
45 13834 : uint32_t res;
46 13834 :
47 13834 : if (__builtin_mul_overflow(a, b, &res)) {
48 9401 : res = UINT32_MAX;
49 9401 : }
50 13834 :
51 13834 : return res;
52 13834 : }
53 :
54 : /**
55 : * If a * b overflows, returns AWS_OP_ERR; otherwise multiplies
56 : * a * b, returns the result in *r, and returns AWS_OP_SUCCESS.
57 : */
58 13408 : AWS_STATIC_IMPL int aws_mul_u32_checked(uint32_t a, uint32_t b, uint32_t *r) {
59 13408 : if (__builtin_mul_overflow(a, b, r)) {
60 12325 : return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
61 12325 : }
62 1083 : return AWS_OP_SUCCESS;
63 1083 : }
64 :
65 : /**
66 : * If a + b overflows, returns AWS_OP_ERR; otherwise adds
67 : * a + b, returns the result in *r, and returns AWS_OP_SUCCESS.
68 : */
69 3047563 : AWS_STATIC_IMPL int aws_add_u64_checked(uint64_t a, uint64_t b, uint64_t *r) {
70 3047563 : if (__builtin_add_overflow(a, b, r)) {
71 62963 : return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
72 62963 : }
73 2984600 : return AWS_OP_SUCCESS;
74 2984600 : }
75 :
76 : /**
77 : * Adds a + b. If the result overflows, returns 2^64 - 1.
78 : */
79 174529 : AWS_STATIC_IMPL uint64_t aws_add_u64_saturating(uint64_t a, uint64_t b) {
80 174529 : uint64_t res;
81 174529 :
82 174529 : if (__builtin_add_overflow(a, b, &res)) {
83 35321 : res = UINT64_MAX;
84 35321 : }
85 174529 :
86 174529 : return res;
87 174529 : }
88 :
89 : /**
90 : * If a + b overflows, returns AWS_OP_ERR; otherwise adds
91 : * a + b, returns the result in *r, and returns AWS_OP_SUCCESS.
92 : */
93 35868 : AWS_STATIC_IMPL int aws_add_u32_checked(uint32_t a, uint32_t b, uint32_t *r) {
94 35868 : if (__builtin_add_overflow(a, b, r)) {
95 19506 : return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
96 19506 : }
97 16362 : return AWS_OP_SUCCESS;
98 16362 : }
99 :
100 : /**
101 : * Adds a + b. If the result overflows, returns 2^32 - 1.
102 : */
103 39397 : AWS_STATIC_IMPL uint32_t aws_add_u32_saturating(uint32_t a, uint32_t b) {
104 39397 : uint32_t res;
105 39397 :
106 39397 : if (__builtin_add_overflow(a, b, &res)) {
107 10738 : res = UINT32_MAX;
108 10738 : }
109 39397 :
110 39397 : return res;
111 39397 : }
112 :
113 : AWS_EXTERN_C_END
114 :
115 : #endif /* AWS_COMMON_MATH_GCC_OVERFLOW_INL */
|