Skip to content

Commit e2ea45a

Browse files
committed
resolve BUGFIX decimal64 parsing overflow
Fixes #344
1 parent 6ef81e2 commit e2ea45a

File tree

2 files changed

+83
-25
lines changed

2 files changed

+83
-25
lines changed

src/resolve.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num)
3636
{
3737
const char *ptr;
3838
int minus = 0;
39-
int64_t ret = 0;
39+
int64_t ret = 0, prev_ret;
4040
int8_t str_exp, str_dig = -1, trailing_zeros = 0;
4141

4242
ptr = *str_num;
@@ -65,7 +65,18 @@ parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num)
6565
}
6666
++str_dig;
6767
} else {
68-
ret = ret * 10 + (ptr[0] - '0');
68+
prev_ret = ret;
69+
if (minus) {
70+
ret = ret * 10 - (ptr[0] - '0');
71+
if (ret > prev_ret) {
72+
return 1;
73+
}
74+
} else {
75+
ret = ret * 10 + (ptr[0] - '0');
76+
if (ret < prev_ret) {
77+
return 1;
78+
}
79+
}
6980
if (str_dig > -1) {
7081
++str_dig;
7182
if (ptr[0] == '0') {
@@ -97,15 +108,17 @@ parse_range_dec64(const char **str_num, uint8_t dig, int64_t *num)
97108
if ((str_exp - 1) + (dig - str_dig) > 18) {
98109
return 1;
99110
}
111+
prev_ret = ret;
100112
ret *= dec_pow(dig - str_dig);
113+
if ((minus && (ret > prev_ret)) || (!minus && (ret < prev_ret))) {
114+
return 1;
115+
}
116+
101117
}
102118
if (str_dig > dig) {
103119
return 1;
104120
}
105121

106-
if (minus) {
107-
ret *= -1;
108-
}
109122
*str_num = ptr;
110123
*num = ret;
111124

tests/data/test_values.c

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ test_validate_value(void **state)
293293
{
294294
struct state *st = (*state);
295295
const struct lys_module *mod;
296-
struct lys_node *a, *b, *c;
296+
struct lys_node *node;
297297
const char *yang = "module x {"
298298
" namespace urn:x;"
299299
" prefix x;"
@@ -318,30 +318,75 @@ test_validate_value(void **state)
318318
" enum alfa;"
319319
" }"
320320
" }"
321+
" leaf d {"
322+
" type decimal64 {"
323+
" fraction-digits 1;"
324+
" }"
325+
" }"
326+
" leaf e {"
327+
" type decimal64 {"
328+
" fraction-digits 10;"
329+
" }"
330+
" }"
331+
" leaf f {"
332+
" type decimal64 {"
333+
" fraction-digits 18;"
334+
" }"
335+
" }"
321336
"}";
322337

323338
mod = lys_parse_mem(st->ctx, yang, LYS_IN_YANG);
324339
assert_ptr_not_equal(mod, NULL);
325340

326-
a = mod->data->next;
327-
assert_int_equal(lyd_validate_value(a, NULL), EXIT_FAILURE); /* empty string is too short */
328-
assert_int_equal(lyd_validate_value(a, "a"), EXIT_FAILURE); /* a is still too short */
329-
assert_int_equal(lyd_validate_value(a, "bbb"), EXIT_FAILURE); /* does not match the pattern */
330-
assert_int_equal(lyd_validate_value(a, "aaaaa"), EXIT_FAILURE); /* too long */
331-
assert_int_equal(lyd_validate_value(a, "aaa"), EXIT_SUCCESS); /* ok */
332-
333-
b = a->next;
334-
assert_int_equal(lyd_validate_value(b, "2"), EXIT_FAILURE); /* too high */
335-
assert_int_equal(lyd_validate_value(b, "-"), EXIT_FAILURE); /* does not match the type (yet) */
336-
assert_int_equal(lyd_validate_value(b, "-2"), EXIT_FAILURE); /* too low */
337-
assert_int_equal(lyd_validate_value(b, "0"), EXIT_SUCCESS); /* ok */
338-
339-
c = b->next;
340-
assert_int_equal(lyd_validate_value(c, "a"), EXIT_FAILURE);
341-
assert_int_equal(lyd_validate_value(c, "al"), EXIT_FAILURE);
342-
assert_int_equal(lyd_validate_value(c, "alf"), EXIT_FAILURE);
343-
assert_int_equal(lyd_validate_value(c, "alfa"), EXIT_SUCCESS); /* ok */
344-
assert_int_equal(lyd_validate_value(c, "alfa "), EXIT_FAILURE);
341+
/* a */
342+
node = mod->data->next;
343+
assert_int_equal(lyd_validate_value(node, NULL), EXIT_FAILURE); /* empty string is too short */
344+
assert_int_equal(lyd_validate_value(node, "a"), EXIT_FAILURE); /* a is still too short */
345+
assert_int_equal(lyd_validate_value(node, "bbb"), EXIT_FAILURE); /* does not match the pattern */
346+
assert_int_equal(lyd_validate_value(node, "aaaaa"), EXIT_FAILURE); /* too long */
347+
assert_int_equal(lyd_validate_value(node, "aaa"), EXIT_SUCCESS); /* ok */
348+
349+
/* b */
350+
node = node->next;
351+
assert_int_equal(lyd_validate_value(node, "2"), EXIT_FAILURE); /* too high */
352+
assert_int_equal(lyd_validate_value(node, "-"), EXIT_FAILURE); /* does not match the type (yet) */
353+
assert_int_equal(lyd_validate_value(node, "-2"), EXIT_FAILURE); /* too low */
354+
assert_int_equal(lyd_validate_value(node, "0"), EXIT_SUCCESS); /* ok */
355+
356+
/* c */
357+
node = node->next;
358+
assert_int_equal(lyd_validate_value(node, "a"), EXIT_FAILURE);
359+
assert_int_equal(lyd_validate_value(node, "al"), EXIT_FAILURE);
360+
assert_int_equal(lyd_validate_value(node, "alf"), EXIT_FAILURE);
361+
assert_int_equal(lyd_validate_value(node, "alfa"), EXIT_SUCCESS); /* ok */
362+
assert_int_equal(lyd_validate_value(node, "alfa "), EXIT_FAILURE);
363+
364+
/* d */
365+
node = node->next;
366+
assert_int_equal(lyd_validate_value(node, "-922337203685477580.9"), EXIT_FAILURE);
367+
assert_int_equal(lyd_validate_value(node, "-925337203685477580"), EXIT_FAILURE);
368+
assert_int_equal(lyd_validate_value(node, "922337203685477580.8"), EXIT_FAILURE);
369+
assert_int_equal(lyd_validate_value(node, "932337203685477580"), EXIT_FAILURE);
370+
assert_int_equal(lyd_validate_value(node, "-922337203685477580.8"), EXIT_SUCCESS); /* ok */
371+
assert_int_equal(lyd_validate_value(node, "922337203685477580.7"), EXIT_SUCCESS); /* ok */
372+
373+
/* e */
374+
node = node->next;
375+
assert_int_equal(lyd_validate_value(node, "-922337203.6854775818"), EXIT_FAILURE);
376+
assert_int_equal(lyd_validate_value(node, "-9223372031"), EXIT_FAILURE);
377+
assert_int_equal(lyd_validate_value(node, "922337203.6854785807"), EXIT_FAILURE);
378+
assert_int_equal(lyd_validate_value(node, "1922337203"), EXIT_FAILURE);
379+
assert_int_equal(lyd_validate_value(node, "-922337203.6854775808"), EXIT_SUCCESS); /* ok */
380+
assert_int_equal(lyd_validate_value(node, "922337203.6854775807"), EXIT_SUCCESS); /* ok */
381+
382+
/* f */
383+
node = node->next;
384+
assert_int_equal(lyd_validate_value(node, "-9.223372036854776808"), EXIT_FAILURE);
385+
assert_int_equal(lyd_validate_value(node, "-10"), EXIT_FAILURE);
386+
assert_int_equal(lyd_validate_value(node, "9.223372136854775807"), EXIT_FAILURE);
387+
assert_int_equal(lyd_validate_value(node, "11"), EXIT_FAILURE);
388+
assert_int_equal(lyd_validate_value(node, "-9.223372036854775808"), EXIT_SUCCESS); /* ok */
389+
assert_int_equal(lyd_validate_value(node, "9.223372036854775807"), EXIT_SUCCESS); /* ok */
345390
}
346391

347392
int main(void)

0 commit comments

Comments
 (0)