From df0d86b847fbf5bd1ad383531cd52b261dc07717 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sat, 19 Sep 2015 23:08:46 +0100 Subject: 36559: test earlier for overflow in pattern range --- ChangeLog | 3 +++ Src/pattern.c | 23 ++++++++++++++++++----- Src/zsh.h | 7 +++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2852b4de9..bb03894a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-09-19 Peter Stephenson + * 36559: Src/pattern.c: test earlier for overflow in pattern + range. + * unposted: Test/D07multibyte.ztst: fix typo. 2015-09-18 Barton E. Schaefer diff --git a/Src/pattern.c b/Src/pattern.c index 3b55ccf1c..af56bd9cc 100644 --- a/Src/pattern.c +++ b/Src/pattern.c @@ -220,8 +220,10 @@ typedef union upat *Upat; #if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT) typedef zlong zrange_t; #define ZRANGE_T_IS_SIGNED (1) +#define ZRANGE_MAX ZLONG_MAX #else typedef unsigned long zrange_t; +#define ZRANGE_MAX ULONG_MAX #endif #ifdef MULTIBYTE_SUPPORT @@ -2641,19 +2643,30 @@ patmatch(Upat prog) start = compend = patinput; comp = 0; while (patinput < patinend && idigit(*patinput)) { - if (comp) - comp *= 10; - comp += *patinput - '0'; + int out_of_range = 0; + int digit = *patinput - '0'; + if (comp > ZRANGE_MAX / (zlong)10) { + out_of_range = 1; + } else { + zrange_t c10 = comp ? comp * 10 : 0; + if (ZRANGE_MAX - c10 < digit) { + out_of_range = 1; + } else { + comp = c10; + comp += digit; + } + } patinput++; compend++; - if (comp & ((zrange_t)1 << (sizeof(comp)*8 - + if (out_of_range || + (comp & ((zrange_t)1 << (sizeof(comp)*8 - #ifdef ZRANGE_T_IS_SIGNED 2 #else 1 #endif - ))) { + )))) { /* * Out of range (allowing for signedness, which * we need if we are using zlongs). diff --git a/Src/zsh.h b/Src/zsh.h index 4e2cb656e..9c7e5d9dc 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -36,6 +36,12 @@ */ #ifdef ZSH_64_BIT_TYPE typedef ZSH_64_BIT_TYPE zlong; +#if defind(ZLONG_IS_LONG_LONG) && defined(LLONG_MAX) +#define ZLONG_MAX LLONG_MAX +#else +/* umm... */ +#define ZLONG_MAX ((zlong)9223372036854775807) +#endif #ifdef ZSH_64_BIT_UTYPE typedef ZSH_64_BIT_UTYPE zulong; #else @@ -44,6 +50,7 @@ typedef unsigned zlong zulong; #else typedef long zlong; typedef unsigned long zulong; +#define ZLONG_MAX LONG_MAX #endif /* -- cgit 1.4.1