Re: Segmentation fault for /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/
Ilya Zakharevich [Tue, 11 Aug 1998 18:43:29 +0000 (14:43 -0400)]
Message-Id: <199808112243.SAA14243@monk.mps.ohio-state.edu>

p4raw-id: //depot/perl@1799

regcomp.c
t/op/re_tests

index 0f883f3..ef651fa 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -252,6 +252,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
     regnode *scan = *scanp, *next;
     I32 delta = 0;
     int is_inf = (flags & SCF_DO_SUBSTR) && (data->flags & SF_IS_INF);
+    int is_inf_internal = 0;           /* The studied chunk is infinite */
     I32 is_par = OP(scan) == OPEN ? ARG(scan) : 0;
     scan_data_t data_fake;
     
@@ -366,7 +367,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                    if (max1 < minnext + deltanext)
                        max1 = minnext + deltanext;
                    if (deltanext == I32_MAX)
-                       is_inf = 1;
+                       is_inf = is_inf_internal = 1;
                    scan = next;
                    if (data_fake.flags & (SF_HAS_PAR|SF_IN_PAR))
                        pars++;
@@ -461,7 +462,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                min++;
                /* Fall through. */
            case STAR:
-               is_inf = 1; 
+               is_inf = is_inf_internal = 1; 
                scan = regnext(scan);
                if (flags & SCF_DO_SUBSTR) {
                    scan_commit(data);
@@ -495,8 +496,10 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                    && maxcount <= 10000) /* Complement check for big count */
                    warner(WARN_UNSAFE, "Strange *+?{} on zero-length expression");
                min += minnext * mincount;
-               is_inf |= (maxcount == REG_INFTY && (minnext + deltanext) > 0
-                          || deltanext == I32_MAX);
+               is_inf_internal |= (maxcount == REG_INFTY 
+                                   && (minnext + deltanext) > 0
+                                  || deltanext == I32_MAX);
+               is_inf |= is_inf_internal;
                delta += (minnext + deltanext) * maxcount - minnext * mincount;
 
                /* Try powerful optimization CURLYX => CURLYN. */
@@ -637,6 +640,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                        }
                        data->longest = &(data->longest_float);
                    }
+                   SvREFCNT_dec(last_str);
                }
                if (data && (fl & SF_HAS_EVAL))
                    data->flags |= SF_HAS_EVAL;
@@ -652,7 +656,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                    scan_commit(data);
                    data->longest = &(data->longest_float);
                }
-               is_inf = 1;
+               is_inf = is_inf_internal = 1;
                break;
            }
        }
@@ -711,7 +715,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
 
   finish:
     *scanp = scan;
-    *deltap = is_inf ? I32_MAX : delta;
+    *deltap = is_inf_internal ? I32_MAX : delta;
     if (flags & SCF_DO_SUBSTR && is_inf) 
        data->pos_delta = I32_MAX - data->pos_min;
     if (is_par > U8_MAX)
@@ -972,9 +976,10 @@ pregcomp(char *exp, char *xend, PMOP *pm)
                && (!(data.flags & SF_FL_BEFORE_MEOL)
                    || (PL_regflags & PMf_MULTILINE)))) {
            if (SvCUR(data.longest_fixed)                       /* ok to leave SvCUR */
-               && data.offset_fixed == data.offset_float_min)
-               goto remove;            /* Like in (a)+. */
-           
+               && data.offset_fixed == data.offset_float_min
+               && SvCUR(data.longest_fixed) == SvCUR(data.longest_float))
+                   goto remove_float;          /* As in (a)+. */
+
            r->float_substr = data.longest_float;
            r->float_min_offset = data.offset_float_min;
            r->float_max_offset = data.offset_float_max;
@@ -986,7 +991,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
                SvTAIL_on(r->float_substr);
        }
        else {
-         remove:
+         remove_float:
            r->float_substr = Nullsv;
            SvREFCNT_dec(data.longest_float);
            longest_float_length = 0;
index 798355a..b6f654f 100644 (file)
@@ -484,3 +484,4 @@ b\z a\nb\n  n       -       -
 b\Z    a\nb    y       -       -
 b\z    a\nb    y       -       -
 (^|x)(c)       ca      y       $2      c
+a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz   x       n       -       -