diff options
author | David Mitchell <davem@iabyn.com> | 2014-12-19 22:52:55 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-12-19 22:52:55 +0000 |
commit | db58a81c116b9bdc669c1b1a8cb7fd33627a926b (patch) | |
tree | 9e9ff71d712f6c848b7f9d57522fe56407411db7 | |
parent | a1b2073ef1dbfca70742296d373883902e6188b7 (diff) | |
download | perl-db58a81c116b9bdc669c1b1a8cb7fd33627a926b.tar.gz |
fix integer overflow in S_regpiece().
RExC_naughty is incremented when nasty bits of regex are found.
If at the end of compilation, its > 01, then PREGf_NAUGHTY is set on the
pattern.
However, some bits of S_regpiece on detecting naughiness, double or nearly
double RExC_naughty, quickly resulting in overflow of the I32.
I've fixed it by skipping the doubling when RExC_naughty is large,
but I don't know whether the doubling is conceptually wrong in the first
place.
Found by -fsanitize=undefined.
-rw-r--r-- | regcomp.c | 6 |
1 files changed, 4 insertions, 2 deletions
@@ -10859,7 +10859,8 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) do_curly: if ((flags&SIMPLE)) { - RExC_naughty += 2 + RExC_naughty / 2; + if (RExC_naughty < I32_MAX / 2) + RExC_naughty += 2 + RExC_naughty / 2; reginsert(pRExC_state, CURLY, ret, depth+1); Set_Node_Offset(ret, parse_start+1); /* MJD */ Set_Node_Cur_Length(ret, parse_start); @@ -10885,7 +10886,8 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) REGTAIL(pRExC_state, ret, reg_node(pRExC_state, NOTHING)); if (SIZE_ONLY) RExC_whilem_seen++, RExC_extralen += 3; - RExC_naughty += 4 + RExC_naughty; /* compound interest */ + if (RExC_naughty < I32_MAX / 4) + RExC_naughty += 4 + RExC_naughty; /* compound interest */ } ret->flags = 0; |