|
18 | 18 | #include <assert.h> |
19 | 19 | #include <string.h> |
20 | 20 | #include <ctype.h> |
| 21 | +#include <inttypes.h> |
21 | 22 | #include <limits.h> |
22 | 23 |
|
23 | 24 | #include "libyang.h" |
@@ -49,12 +50,46 @@ struct parsed_pred { |
49 | 50 | } *pred; |
50 | 51 | }; |
51 | 52 |
|
| 53 | +static int |
| 54 | +check_overflow_mul(int64_t num1, int64_t num2) |
| 55 | +{ |
| 56 | + if (((num1 == -1) && (num2 == INT64_MIN)) || ((num2 == -1) && (num1 == INT64_MIN))) { |
| 57 | + return 1; |
| 58 | + } |
| 59 | + |
| 60 | + if ((num1 > INT64_MAX / num2) || (num1 < INT64_MIN / num2)) { |
| 61 | + return 1; |
| 62 | + } |
| 63 | + |
| 64 | + return 0; |
| 65 | +} |
| 66 | + |
| 67 | +static int |
| 68 | +check_overflow_sub(int64_t num1, int64_t num2) |
| 69 | +{ |
| 70 | + if (((num2 < 0) && (num1 > INT64_MAX + num2)) || ((num2 > 0) && (num1 < INT64_MIN + num2))) { |
| 71 | + return 1; |
| 72 | + } |
| 73 | + |
| 74 | + return 0; |
| 75 | +} |
| 76 | + |
| 77 | +static int |
| 78 | +check_overflow_add(int64_t num1, int64_t num2) |
| 79 | +{ |
| 80 | + if (((num2 > 0) && (num1 > INT64_MAX - num2)) || ((num2 < 0) && (num1 < INT64_MIN - num2))) { |
| 81 | + return 1; |
| 82 | + } |
| 83 | + |
| 84 | + return 0; |
| 85 | +} |
| 86 | + |
52 | 87 | int |
53 | 88 | parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num) |
54 | 89 | { |
55 | 90 | const char *ptr; |
56 | 91 | int minus = 0; |
57 | | - int64_t ret = 0, prev_ret; |
| 92 | + int64_t ret = 0; |
58 | 93 | int8_t str_exp, str_dig = -1, trailing_zeros = 0; |
59 | 94 |
|
60 | 95 | ptr = *str_num; |
@@ -83,17 +118,21 @@ parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num) |
83 | 118 | } |
84 | 119 | ++str_dig; |
85 | 120 | } else { |
86 | | - prev_ret = ret; |
| 121 | + if (check_overflow_mul(ret, 10)) { |
| 122 | + return 1; |
| 123 | + } |
| 124 | + ret *= 10; |
| 125 | + |
87 | 126 | if (minus) { |
88 | | - ret = ret * 10 - (ptr[0] - '0'); |
89 | | - if (ret > prev_ret) { |
| 127 | + if (check_overflow_sub(ret, ptr[0] - '0')) { |
90 | 128 | return 1; |
91 | 129 | } |
| 130 | + ret -= ptr[0] - '0'; |
92 | 131 | } else { |
93 | | - ret = ret * 10 + (ptr[0] - '0'); |
94 | | - if (ret < prev_ret) { |
| 132 | + if (check_overflow_add(ret, ptr[0] - '0')) { |
95 | 133 | return 1; |
96 | 134 | } |
| 135 | + ret += ptr[0] - '0'; |
97 | 136 | } |
98 | 137 | if (str_dig > -1) { |
99 | 138 | ++str_dig; |
@@ -126,12 +165,11 @@ parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num) |
126 | 165 | if ((str_exp - 1) + (dig - str_dig) > 18) { |
127 | 166 | return 1; |
128 | 167 | } |
129 | | - prev_ret = ret; |
130 | | - ret *= dec_pow(dig - str_dig); |
131 | | - if ((minus && (ret > prev_ret)) || (!minus && (ret < prev_ret))) { |
| 168 | + |
| 169 | + if (check_overflow_mul(ret, dec_pow(dig - str_dig))) { |
132 | 170 | return 1; |
133 | 171 | } |
134 | | - |
| 172 | + ret *= dec_pow(dig - str_dig); |
135 | 173 | } |
136 | 174 | if (str_dig > dig) { |
137 | 175 | return 1; |
|
0 commit comments