From eaf4f23176ddcc005531b6e3e538dca382b29d31 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 11 Nov 2021 14:29:57 +0100 Subject: erts: Fix integer overflow problem in WSTACK In the testcase binary_SUITE:t2b_deterministic a very large hash map is created and encoded. This lead to a WSTACK_RESERVE call with an N value of 4 000 000 which made the pointer wrap around zero and thus the stack was not grown as it should. As far as I can tell this can only happen in the new deterministic term_to_binary. --- erts/emulator/beam/global.h | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 904d394fca..3eb0225b4e 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -642,28 +642,29 @@ do { \ #define WSTACK_IS_STATIC(s) (s.wstart == WSTK_DEF_STACK(s)) -#define WSTACK_PUSH(s, x) \ -do { \ - if (s.wsp == s.wend) { \ - erl_grow_wstack(&s, 1); \ - } \ - *s.wsp++ = (x); \ +#define WSTACK_RESERVE(s, push_cnt) \ +do { \ + if (s.wend - s.wsp < (Sint)(push_cnt)) { \ + erl_grow_wstack(&s, (push_cnt)); \ + } \ +} while(0) + +#define WSTACK_PUSH(s, x) \ +do { \ + WSTACK_RESERVE(s, 1); \ + *s.wsp++ = (x); \ } while(0) #define WSTACK_PUSH2(s, x, y) \ do { \ - if (s.wsp > s.wend - 2) { \ - erl_grow_wstack(&s, 2); \ - } \ + WSTACK_RESERVE(s, 2); \ *s.wsp++ = (x); \ *s.wsp++ = (y); \ } while(0) #define WSTACK_PUSH3(s, x, y, z) \ do { \ - if (s.wsp > s.wend - 3) { \ - erl_grow_wstack(&s, 3); \ - } \ + WSTACK_RESERVE(s, 3); \ *s.wsp++ = (x); \ *s.wsp++ = (y); \ *s.wsp++ = (z); \ @@ -671,9 +672,7 @@ do { \ #define WSTACK_PUSH4(s, A1, A2, A3, A4) \ do { \ - if (s.wsp > s.wend - 4) { \ - erl_grow_wstack(&s, 4); \ - } \ + WSTACK_RESERVE(s, 4); \ *s.wsp++ = (A1); \ *s.wsp++ = (A2); \ *s.wsp++ = (A3); \ @@ -682,9 +681,7 @@ do { \ #define WSTACK_PUSH5(s, A1, A2, A3, A4, A5) \ do { \ - if (s.wsp > s.wend - 5) { \ - erl_grow_wstack(&s, 5); \ - } \ + WSTACK_RESERVE(s, 5); \ *s.wsp++ = (A1); \ *s.wsp++ = (A2); \ *s.wsp++ = (A3); \ @@ -694,9 +691,7 @@ do { \ #define WSTACK_PUSH6(s, A1, A2, A3, A4, A5, A6) \ do { \ - if (s.wsp > s.wend - 6) { \ - erl_grow_wstack(&s, 6); \ - } \ + WSTACK_RESERVE(s, 6); \ *s.wsp++ = (A1); \ *s.wsp++ = (A2); \ *s.wsp++ = (A3); \ @@ -705,13 +700,6 @@ do { \ *s.wsp++ = (A6); \ } while(0) -#define WSTACK_RESERVE(s, push_cnt) \ -do { \ - if (s.wsp > s.wend - (push_cnt)) { \ - erl_grow_wstack(&s, (push_cnt)); \ - } \ -} while(0) - /* Must be preceded by WSTACK_RESERVE */ #define WSTACK_FAST_PUSH(s, x) \ do { \ -- cgit v1.2.1 From d26eff597c5f4a9a79055e85b8d59fa5f7ca4698 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 12 Nov 2021 14:00:44 +0100 Subject: erts: Fix potential integer overflow in ESTACK If ESTACK_RESERVE is called with a large enough N then the subtraction would overflow and the stack would not be grown as it should. As far as I can tell this is never done so this fix is to protect against future use. --- erts/emulator/beam/global.h | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 3eb0225b4e..9176309e42 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -443,28 +443,29 @@ do { \ #define ESTACK_IS_STATIC(s) ((s).start == ESTK_DEF_STACK(s)) +#define ESTACK_RESERVE(s, push_cnt) \ +do { \ + if ((s).end - (s).sp < (Sint)(push_cnt)) { \ + erl_grow_estack(&(s), (push_cnt)); \ + } \ +} while(0) + #define ESTACK_PUSH(s, x) \ do { \ - if ((s).sp == (s).end) { \ - erl_grow_estack(&(s), 1); \ - } \ + ESTACK_RESERVE(s, 1); \ *(s).sp++ = (x); \ } while(0) #define ESTACK_PUSH2(s, x, y) \ do { \ - if ((s).sp > (s).end - 2) { \ - erl_grow_estack(&(s), 2); \ - } \ + ESTACK_RESERVE(s, 2); \ *(s).sp++ = (x); \ *(s).sp++ = (y); \ } while(0) #define ESTACK_PUSH3(s, x, y, z) \ do { \ - if ((s).sp > (s).end - 3) { \ - erl_grow_estack(&s, 3); \ - } \ + ESTACK_RESERVE(s, 3); \ *(s).sp++ = (x); \ *(s).sp++ = (y); \ *(s).sp++ = (z); \ @@ -472,22 +473,13 @@ do { \ #define ESTACK_PUSH4(s, E1, E2, E3, E4) \ do { \ - if ((s).sp > (s).end - 4) { \ - erl_grow_estack(&s, 4); \ - } \ + ESTACK_RESERVE(s, 4); \ *(s).sp++ = (E1); \ *(s).sp++ = (E2); \ *(s).sp++ = (E3); \ *(s).sp++ = (E4); \ } while(0) -#define ESTACK_RESERVE(s, push_cnt) \ -do { \ - if ((s).sp > (s).end - (push_cnt)) { \ - erl_grow_estack(&(s), (push_cnt)); \ - } \ -} while(0) - /* Must be preceded by ESTACK_RESERVE */ #define ESTACK_FAST_PUSH(s, x) \ do { \ -- cgit v1.2.1