Ignore:
Timestamp:
Jan 1, 2007, 9:13:00 PM (18 years ago)
Author:
ddkilzer
Message:

JavaScriptCore:

Reviewed by Darin.

Modified pcre_compile() (and the functions that it calls) to work with patterns
containing null characters.

Covered by JavaScriptCore tests ecma_3/RegExp/octal-002.js and ecma_3/RegExp/regress-85721.js

  • kjs/regexp.cpp: (KJS::RegExp::RegExp): Changed to not null-terminate the pattern string and instead pass its length to pcre_compile.
  • pcre/pcre.h:
  • pcre/pcre_compile.c: (check_escape): (get_ucp): (is_counted_repeat): (check_posix_syntax): (compile_branch): (compile_regex): (pcre_compile): Added a parameter specifying the length of the pattern, which is no longer required to be null-terminated and may contain null characters. (pcre_compile2):
  • pcre/pcre_internal.h:
  • tests/mozilla/expected.html: Updated for the two tests that this patch fixes. Also updated failing results for ecma_3/RegExp/regress-100199.js which were not updated after bug 6257 was fixed.

WebCore:

Reviewed by Darin.

  • platform/RegularExpression.cpp: (WebCore::RegularExpression::Private::compile): Changed to not null-terminate the pattern string and instead pass its length to pcre_compile.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/pcre/pcre_compile.c

    r18498 r18517  
    356356
    357357static BOOL
    358   compile_regex(int, int, int *, uschar **, const pcre_uchar **, int *, BOOL, int,
     358  compile_regex(int, int, int *, uschar **, const pcre_uchar **, const pcre_uchar const*, int *, BOOL, int,
    359359    int *, int *, branch_chain *, compile_data *);
    360360
     
    384384
    385385static int
    386 check_escape(const pcre_uchar **ptrptr, int *errorcodeptr, int bracount,
     386check_escape(const pcre_uchar **ptrptr, const pcre_uchar const* patternEnd, int *errorcodeptr, int bracount,
    387387  int options, BOOL isclass)
    388388{
     
    392392/* If backslash is at the end of the pattern, it's an error. */
    393393
    394 c = *(++ptr);
    395 if (c == 0) *errorcodeptr = ERR1;
     394if (++ptr == patternEnd) {
     395    *errorcodeptr = ERR1;
     396    *ptrptr = ptr;
     397    return 0;
     398}
     399
     400c = *ptr;
    396401
    397402/* Non-alphamerics are literals. For digits or letters, do an initial lookup in
     
    400405
    401406#if !EBCDIC    /* ASCII coding */
    402 else if (c < '0' || c > 'z') {}                           /* Not alphameric */
     407if (c < '0' || c > 'z') {}                           /* Not alphameric */
    403408else if ((i = escapes[c - '0']) != 0) c = i;
    404409
    405410#else          /* EBCDIC coding */
    406 else if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {}   /* Not alphameric */
     411if (c < 'a' || (ebcdic_chartab[c] & 0x0E) == 0) {}   /* Not alphameric */
    407412else if ((i = escapes[c - 0x48]) != 0)  c = i;
    408413#endif
     
    445450      oldptr = ptr;
    446451      c -= '0';
    447       while ((DIGITAB(ptr[1]) & ctype_digit) != 0)
     452      while (ptr + 1 < patternEnd && (DIGITAB(ptr[1]) & ctype_digit) != 0)
    448453        c = c * 10 + *(++ptr) - '0';
    449454      if (c < 10 || c <= bracount)
     
    471476    case '0':
    472477    c -= '0';
    473     while(i++ < 2 && ptr[1] >= '0' && ptr[1] <= '7')
     478    while (i++ < 2 && ptr + 1 < patternEnd && ptr[1] >= '0' && ptr[1] <= '7')
    474479        c = c * 8 + *(++ptr) - '0';
    475480    c &= 255;     /* Take least significant 8 bits */
     
    481486    case 'x':
    482487#ifdef SUPPORT_UTF8
    483     if (ptr[1] == '{' && (options & PCRE_UTF8) != 0)
     488    if (ptr + 1 < patternEnd && ptr[1] == '{' && (options & PCRE_UTF8) != 0)
    484489      {
    485490      const pcre_uchar *pt = ptr + 2;
    486491      register int count = 0;
    487492      c = 0;
    488       while ((DIGITAB(*pt) & ctype_xdigit) != 0)
     493      while (pt < patternEnd && (DIGITAB(*pt) & ctype_xdigit) != 0)
    489494        {
    490495        int cc = *pt++;
     
    498503#endif
    499504        }
    500       if (*pt == '}')
     505      if (pt < patternEnd && *pt == '}')
    501506        {
    502507        if (c < 0 || count > 8 || (c >= 0xd800 && c <= 0xdbff) || (c >= 0xfdd0 && c <= 0xfdef) || c == 0xfffe || c == 0xffff || c > 0x10FFFF) *errorcodeptr = ERR34;
     
    512517
    513518    c = 0;
    514     while (i++ < 2 && (DIGITAB(ptr[1]) & ctype_xdigit) != 0)
     519    while (i++ < 2 && ptr + 1 < patternEnd && (DIGITAB(ptr[1]) & ctype_xdigit) != 0)
    515520      {
    516521      int cc;                               /* Some compilers don't like ++ */
     
    529534
    530535    case 'c':
    531     c = *(++ptr);
    532     if (c == 0)
     536    if (++ptr == patternEnd)
    533537      {
    534538      *errorcodeptr = ERR2;
    535539      return 0;
    536540      }
     541    c = *ptr;
    537542
    538543    /* A letter is upper-cased; then the 0x40 bit is flipped. This coding
     
    591596
    592597static int
    593 get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, int *errorcodeptr)
     598get_ucp(const pcre_uchar **ptrptr, const pcre_uchar const* patternEnd, BOOL *negptr, int *errorcodeptr)
    594599{
    595600int c, i, bot, top;
     
    597602char name[4];
    598603
    599 c = *(++ptr);
    600 if (c == 0) goto ERROR_RETURN;
     604if (++ptr == patternEnd) goto ERROR_RETURN;
     605c = *ptr;
    601606
    602607*negptr = FALSE;
     
    607612if (c == '{')
    608613  {
    609   if (ptr[1] == '^')
     614  if (ptr + 1 < patternEnd && ptr[1] == '^')
    610615    {
    611616    *negptr = TRUE;
     
    614619  for (i = 0; i <= 2; i++)
    615620    {
    616     c = *(++ptr);
    617     if (c == 0) goto ERROR_RETURN;
     621    if (++ptr == patternEnd) goto ERROR_RETURN;
     622    c = *ptr;
    618623    if (c == '}') break;
    619624    if (c > 127) goto ERROR_RETURN;
     
    622627  if (c !='}')   /* Try to distinguish error cases */
    623628    {
    624     while (*(++ptr) != 0 && *ptr != '}');
     629    while (++ptr < patternEnd && *ptr != '}')
     630        ;
    625631    if (*ptr == '}') goto UNKNOWN_RETURN; else goto ERROR_RETURN;
    626632    }
     
    683689
    684690static BOOL
    685 is_counted_repeat(const pcre_uchar *p)
     691is_counted_repeat(const pcre_uchar *p, const pcre_uchar const* patternEnd)
    686692{
    687 if ((DIGITAB(*p) & ctype_digit) == 0) return FALSE;
     693if (p >= patternEnd || (DIGITAB(*p) & ctype_digit) == 0)
     694    return FALSE;
    688695p++;
    689 while ((DIGITAB(*p) & ctype_digit) != 0) p++;
    690 if (*p == '}') return TRUE;
    691 
    692 if (*p++ != ',') return FALSE;
    693 if (*p == '}') return TRUE;
    694 
    695 if ((DIGITAB(*p) & ctype_digit) == 0) return FALSE;
     696while (p < patternEnd && (DIGITAB(*p) & ctype_digit) != 0)
     697    p++;
     698if (p < patternEnd && *p == '}')
     699    return TRUE;
     700
     701if (p >= patternEnd || *p++ != ',')
     702    return FALSE;
     703if (p < patternEnd && *p == '}')
     704    return TRUE;
     705
     706if (p >= patternEnd || (DIGITAB(*p) & ctype_digit) == 0)
     707    return FALSE;
    696708p++;
    697 while ((DIGITAB(*p) & ctype_digit) != 0) p++;
    698 
    699 return (*p == '}');
     709while (p < patternEnd && (DIGITAB(*p) & ctype_digit) != 0)
     710    p++;
     711
     712return (p < patternEnd && *p == '}');
    700713}
    701714
     
    13601373
    13611374static BOOL
    1362 check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr, compile_data *cd)
     1375check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar const *patternEnd, const pcre_uchar **endptr, compile_data *cd)
    13631376{
    13641377int terminator;          /* Don't combine these lines; the Solaris cc */
    13651378terminator = *(++ptr);   /* compiler warns about "non-constant" initializer. */
    13661379if (*(++ptr) == '^') ptr++;
    1367 while ((CTYPES(cd, *ptr) & ctype_letter) != 0) ptr++;
    1368 if (*ptr == terminator && ptr[1] == ']')
     1380while (ptr < patternEnd && (CTYPES(cd, *ptr) & ctype_letter) != 0)
     1381    ptr++;
     1382if (ptr + 1 < patternEnd && *ptr == terminator && ptr[1] == ']')
    13691383  {
    13701384  *endptr = ptr;
     
    15861600static BOOL
    15871601compile_branch(int *optionsptr, int *brackets, uschar **codeptr,
    1588   const pcre_uchar **ptrptr, int *errorcodeptr, int *firstbyteptr,
     1602  const pcre_uchar **ptrptr, const pcre_uchar const* patternEnd, int *errorcodeptr, int *firstbyteptr,
    15891603  int *reqbyteptr, branch_chain *bcptr, compile_data *cd)
    15901604{
     
    16621676  /* Next byte in the pattern */
    16631677
    1664   c = *ptr;
     1678  c = ptr < patternEnd ? *ptr : 0;
    16651679
    16661680  /* If in \Q...\E, check for the end; if not, we have a literal */
    16671681
    1668   if (inescq && c != 0)
     1682  if (inescq && ptr < patternEnd)
    16691683    {
    1670     if (c == '\\' && ptr[1] == 'E')
     1684    if (c == '\\' && ptr + 1 < patternEnd && ptr[1] == 'E')
    16711685      {
    16721686      inescq = FALSE;
     
    16941708
    16951709  is_quantifier = c == '*' || c == '+' || c == '?' ||
    1696     (c == '{' && is_counted_repeat(ptr+1));
     1710    (c == '{' && is_counted_repeat(ptr+1, patternEnd));
    16971711
    16981712  if (!is_quantifier && previous_callout != NULL &&
     
    17101724    if (c == '#')
    17111725      {
    1712       /* The space before the ; is to avoid a warning on a silly compiler
    1713       on the Macintosh. */
    1714       while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
    1715       if (c != 0) continue;   /* Else fall through to handle end of string */
     1726      while (++ptr < patternEnd && (c = *ptr) != NEWLINE)
     1727          ;
     1728      if (ptr < patternEnd)
     1729          continue;   /* Else fall through to handle end of string */
     1730      c = 0;
    17161731      }
    17171732    }
     
    17301745
    17311746    case 0:
     1747        if (ptr < patternEnd)
     1748            goto NORMAL_CHAR;
     1749        // End of string; fall through
    17321750    case '|':
    17331751    case ')':
     
    17851803
    17861804    if ((ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
    1787         check_posix_syntax(ptr, &tempptr, cd))
     1805        check_posix_syntax(ptr, patternEnd, &tempptr, cd))
    17881806      {
    17891807      *errorcodeptr = (ptr[1] == ':')? ERR13 : ERR31;
     
    18581876      if (c == '[' &&
    18591877          (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
    1860           check_posix_syntax(ptr, &tempptr, cd))
     1878          check_posix_syntax(ptr, patternEnd, &tempptr, cd))
    18611879        {
    18621880        BOOL local_negate = FALSE;
     
    19001918        for (i = 0; i < 3; i++)
    19011919          {
    1902           BOOL blankclass = STREQUAL(ptr, 5, "blank");
     1920          BOOL blankclass = ptr + 5 <= patternEnd && STREQUAL(ptr, 5, "blank");
    19031921          int taboffset = posix_class_maps[posix_class + i];
    19041922          if (taboffset < 0) break;
     
    19331951      if (c == '\\')
    19341952        {
    1935         c = check_escape(&ptr, errorcodeptr, *brackets, options, TRUE);
     1953        c = check_escape(&ptr, patternEnd, errorcodeptr, *brackets, options, TRUE);
    19361954
    19371955        if (-c == ESC_b) c = '\b';       /* \b is backslash in a class */
     
    19391957        else if (-c == ESC_Q)            /* Handle start of quoted string */
    19401958          {
    1941           if (ptr[1] == '\\' && ptr[2] == 'E')
     1959          if (ptr + 2 < patternEnd && ptr[1] == '\\' && ptr[2] == 'E')
    19421960            {
    19431961            ptr += 2; /* avoid empty string */
     
    19862004              {
    19872005              BOOL negated;
    1988               int property = get_ucp(&ptr, &negated, errorcodeptr);
     2006              int property = get_ucp(&ptr, patternEnd, &negated, errorcodeptr);
    19892007              if (property < 0) goto FAILED;
    19902008              class_utf8 = TRUE;
     
    20422060          {
    20432061          const pcre_uchar *oldptr = ptr;
    2044           d = check_escape(&ptr, errorcodeptr, *brackets, options, TRUE);
     2062          d = check_escape(&ptr, patternEnd, errorcodeptr, *brackets, options, TRUE);
    20452063
    20462064          /* \b is backslash; \X is literal X; any other special means the '-'
     
    23762394    repeat type to the non-default. */
    23772395
    2378     if (ptr[1] == '+')
     2396    if (ptr + 1 < patternEnd && ptr[1] == '+')
    23792397      {
    23802398      repeat_type = 0;                  /* Force greedy */
     
    23822400      ptr++;
    23832401      }
    2384     else if (ptr[1] == '?')
     2402    else if (ptr + 1 < patternEnd && ptr[1] == '?')
    23852403      {
    23862404      repeat_type = greedy_non_default;
     
    31773195         &tempcode,                    /* Where to put code (updated) */
    31783196         &ptr,                         /* Input pointer (updated) */
     3197         patternEnd,
    31793198         errorcodeptr,                 /* Where to put an error message */
    31803199         (bravalue == OP_ASSERTBACK ||
     
    32763295    /* Error if hit end of pattern */
    32773296
    3278     if (*ptr != ')')
     3297    if (ptr > patternEnd || *ptr != ')')
    32793298      {
    32803299      *errorcodeptr = ERR14;
     
    32893308    case '\\':
    32903309    tempptr = ptr;
    3291     c = check_escape(&ptr, errorcodeptr, *brackets, options, FALSE);
     3310    c = check_escape(&ptr, patternEnd, errorcodeptr, *brackets, options, FALSE);
    32923311
    32933312    /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
     
    33023321      if (-c == ESC_Q)            /* Handle start of quoted string */
    33033322        {
    3304         if (ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */
     3323        if (ptr + 2 < patternEnd && ptr[1] == '\\' && ptr[2] == 'E') ptr += 2; /* avoid empty string */
    33053324          else inescq = TRUE;
    33063325        continue;
     
    33353354        {
    33363355        BOOL negated;
    3337         int value = get_ucp(&ptr, &negated, errorcodeptr);
     3356        int value = get_ucp(&ptr, patternEnd, &negated, errorcodeptr);
    33383357        previous = code;
    33393358        *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
     
    33913410    if (utf8 && (c & 0xc0) == 0xc0)
    33923411      {
    3393       while ((ptr[1] & 0xc0) == 0x80)
     3412      while (ptr + 1 < patternEnd && (ptr[1] & 0xc0) == 0x80)
    33943413        mcbuffer[mclength++] = *(++ptr);
    33953414      }
     
    34843503static BOOL
    34853504compile_regex(int options, int oldims, int *brackets, uschar **codeptr,
    3486   const pcre_uchar **ptrptr, int *errorcodeptr, BOOL lookbehind, int skipbytes,
     3505  const pcre_uchar **ptrptr, const pcre_uchar const* patternEnd, int *errorcodeptr, BOOL lookbehind, int skipbytes,
    34873506  int *firstbyteptr, int *reqbyteptr, branch_chain *bcptr, compile_data *cd)
    34883507{
     
    35293548  /* Now compile the branch */
    35303549
    3531   if (!compile_branch(&options, brackets, &code, &ptr, errorcodeptr,
     3550  if (!compile_branch(&options, brackets, &code, &ptr, patternEnd, errorcodeptr,
    35323551        &branchfirstbyte, &branchreqbyte, &bc, cd))
    35333552    {
     
    36033622  at the terminating char. */
    36043623
    3605   if (*ptr != '|')
     3624  if (ptr >= patternEnd || *ptr != '|')
    36063625    {
    36073626    int length = INT_CAST(code - last_branch);
     
    36233642    /* Resetting option if needed */
    36243643
    3625     if ((options & PCRE_IMS) != oldims && *ptr == ')')
     3644    if ((options & PCRE_IMS) != oldims && ptr < patternEnd && *ptr == ')')
    36263645      {
    36273646      *code++ = OP_OPT;
     
    39043923
    39053924PCRE_EXPORT pcre *
    3906 pcre_compile(const pcre_char *pattern, int options, const char **errorptr,
     3925pcre_compile(const pcre_char *pattern, int patternLength, int options, const char **errorptr,
    39073926  int *erroroffset, const unsigned char *tables)
    39083927{
    3909 return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
     3928return pcre_compile2(pattern, patternLength, options, NULL, errorptr, erroroffset, tables);
    39103929}
    39113930
    39123931
    39133932PCRE_EXPORT pcre *
    3914 pcre_compile2(const pcre_char *pattern, int options, int *errorcodeptr,
     3933pcre_compile2(const pcre_char *pattern, int patternLength, int options, int *errorcodeptr,
    39153934  const char **errorptr, int *erroroffset, const unsigned char *tables)
    39163935{
     
    40274046
    40284047ptr = (const pcre_uchar *)(pattern - 1);
    4029 while ((c = *(++ptr)) != 0)
     4048const pcre_uchar const* patternEnd = (const pcre_uchar *)(pattern + patternLength);
     4049
     4050while (++ptr < patternEnd)
    40304051  {
     4052  c = *ptr;
     4053 
    40314054  int min, max;
    40324055  int class_optcount;
     
    40494072    if (c == '#')
    40504073      {
    4051       /* The space before the ; is to avoid a warning on a silly compiler
    4052       on the Macintosh. */
    4053       while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
    4054       if (c == 0) break;
     4074      while (++ptr < patternEnd && (c = *ptr) != NEWLINE)
     4075        ;
     4076      if (ptr == patternEnd)
     4077        break;
    40554078      continue;
    40564079      }
     
    40634086  if ((options & PCRE_AUTO_CALLOUT) != 0 &&
    40644087       c != '*' && c != '+' && c != '?' &&
    4065        (c != '{' || !is_counted_repeat(ptr + 1)))
     4088       (c != '{' || !is_counted_repeat(ptr + 1, patternEnd)))
    40664089    length += 2 + 2*LINK_SIZE;
    40674090
     
    40724095
    40734096    case '\\':
    4074     c = check_escape(&ptr, &errorcode, bracount, options, FALSE);
     4097    c = check_escape(&ptr, patternEnd, &errorcode, bracount, options, FALSE);
    40754098    if (errorcode != 0) goto PCRE_ERROR_RETURN;
    40764099
     
    41224145      length += 2;
    41234146      lastitemlength = 2;
    4124       if (get_ucp(&ptr, &negated, &errorcode) < 0) goto PCRE_ERROR_RETURN;
     4147      if (get_ucp(&ptr, patternEnd, &negated, &errorcode) < 0) goto PCRE_ERROR_RETURN;
    41254148      continue;
    41264149#else
     
    41454168        compile_block.top_backref = refnum;
    41464169      length += 2;   /* For single back reference */
    4147       if (ptr[1] == '{' && is_counted_repeat(ptr+2))
     4170      if (ptr + 1 < patternEnd && ptr[1] == '{' && is_counted_repeat(ptr+2, patternEnd))
    41484171        {
    41494172        ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode);
     
    41534176            length++;
    41544177        else length += 5;
    4155         if (ptr[1] == '?') ptr++;
     4178        if (ptr + 1 < patternEnd && ptr[1] == '?')
     4179            ptr++;
    41564180        }
    41574181      }
     
    41754199
    41764200    case '{':
    4177     if (!is_counted_repeat(ptr+1)) goto NORMAL_CHAR;
     4201    if (!is_counted_repeat(ptr+1, patternEnd))
     4202        goto NORMAL_CHAR;
    41784203    ptr = read_repeat_counts(ptr+1, &min, &max, &errorcode);
    41794204    if (errorcode != 0) goto PCRE_ERROR_RETURN;
     
    41974222      }
    41984223
    4199     if (ptr[1] == '?') ptr++;      /* Needs no extra length */
     4224    if (ptr + 1 < patternEnd && ptr[1] == '?')
     4225        ptr++;                     /* Needs no extra length */
    42004226
    42014227    POSESSIVE:                     /* Test for possessive quantifier */
    4202     if (ptr[1] == '+')
     4228    if (ptr + 1 < patternEnd && ptr[1] == '+')
    42034229      {
    42044230      ptr++;
     
    42254251
    42264252    case '[':
    4227     if (*(++ptr) == '^')
     4253    if (++ptr < patternEnd && *ptr == '^')
    42284254      {
    42294255      class_optcount = 10;  /* Greater than one */
     
    42384264    /* Written as a "do" so that an initial ']' is taken as data */
    42394265
    4240     if (*ptr != 0) do
     4266    if (ptr < patternEnd) do
    42414267      {
    42424268      /* Inside \Q...\E everything is literal except \E */
     
    42444270      if (inescq)
    42454271        {
    4246         if (*ptr != '\\' || ptr[1] != 'E') goto GET_ONE_CHARACTER;
     4272        if (*ptr != '\\' || ptr + 1 >= patternEnd || ptr[1] != 'E')
     4273            goto GET_ONE_CHARACTER;
    42474274        inescq = FALSE;
    42484275        ptr += 1;
     
    42544281      if (*ptr == '\\')
    42554282        {
    4256         c = check_escape(&ptr, &errorcode, bracount, options, TRUE);
     4283        c = check_escape(&ptr, patternEnd, &errorcode, bracount, options, TRUE);
    42574284        if (errorcode != 0) goto PCRE_ERROR_RETURN;
    42584285
     
    42974324      checked during the real compile phase. */
    42984325
    4299       else if (*ptr == '[' && check_posix_syntax(ptr, &ptr, &compile_block))
     4326      else if (*ptr == '[' && ptr + 2 < patternEnd && check_posix_syntax(ptr, patternEnd, &ptr, &compile_block))
    43004327        {
    43014328        ptr++;
     
    43194346          {
    43204347          int extra = 0;
    4321           GETCHARLEN(c, ptr, extra);
     4348          GETCHARLENEND(c, ptr, patternEnd, extra);
    43224349          ptr += extra;
    43234350          }
     
    43334360
    43344361        d = -1;
    4335         if (ptr[1] == '-')
     4362        if (ptr + 1 < patternEnd && ptr[1] == '-')
    43364363          {
    43374364          pcre_uchar const *hyptr = ptr++;
    4338           if (ptr[1] == '\\')
    4339             {
    4340             ptr++;
    4341             d = check_escape(&ptr, &errorcode, bracount, options, TRUE);
    4342             if (errorcode != 0) goto PCRE_ERROR_RETURN;
    4343             if (-d == ESC_b) d = '\b';        /* backspace */
    4344             else if (-d == ESC_X) d = 'X';    /* literal X in a class */
    4345             }
    4346           else if (ptr[1] != 0 && ptr[1] != ']')
    4347             {
    4348             ptr++;
    4349 #ifdef SUPPORT_UTF8
    4350             if (utf8)
    4351               {
    4352               int extra = 0;
    4353               GETCHARLEN(d, ptr, extra);
    4354               ptr += extra;
    4355               }
    4356             else
    4357 #endif
    4358             d = *ptr;
    4359             }
     4365          if (ptr + 1 < patternEnd) {
     4366              if (ptr[1] == '\\')
     4367                {
     4368                ptr++;
     4369                d = check_escape(&ptr, patternEnd, &errorcode, bracount, options, TRUE);
     4370                if (errorcode != 0) goto PCRE_ERROR_RETURN;
     4371                if (-d == ESC_b) d = '\b';        /* backspace */
     4372                else if (-d == ESC_X) d = 'X';    /* literal X in a class */
     4373                }
     4374              else if (ptr[1] != ']')
     4375                {
     4376                ptr++;
     4377    #ifdef SUPPORT_UTF8
     4378                if (utf8)
     4379                  {
     4380                  int extra = 0;
     4381                  GETCHARLENEND(d, ptr, patternEnd, extra);
     4382                  ptr += extra;
     4383                  }
     4384                else
     4385    #endif
     4386                d = *ptr;
     4387                }
     4388          }
    43604389          if (d < 0) ptr = hyptr;      /* go back to hyphen as data */
    43614390          }
     
    44544483        }
    44554484      }
    4456     while (*(++ptr) != 0 && (inescq || *ptr != ']')); /* Concludes "do" above */
    4457 
    4458     if (*ptr == 0)                          /* Missing terminating ']' */
     4485    while (++ptr < patternEnd && (inescq || *ptr != ']')); /* Concludes "do" above */
     4486
     4487    if (ptr >= patternEnd)                          /* Missing terminating ']' */
    44594488      {
    44604489      errorcode = ERR6;
     
    44734502      we also need extra for wrapping the whole thing in a sub-pattern. */
    44744503
    4475       if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2))
     4504      if (ptr + 1 < patternEnd && ptr[1] == '{' && is_counted_repeat(ptr+2, patternEnd))
    44764505        {
    44774506        ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode);
     
    44814510            length++;
    44824511        else length += 5;
    4483         if (ptr[1] == '+')
    4484           {
    4485           ptr++;
    4486           length += 2 + 2*LINK_SIZE;
    4487           }
    4488         else if (ptr[1] == '?') ptr++;
     4512        if (ptr + 1 < patternEnd) {
     4513            if (ptr[1] == '+')
     4514              {
     4515              ptr++;
     4516              length += 2 + 2*LINK_SIZE;
     4517              }
     4518            else if (ptr[1] == '?')
     4519                ptr++;
     4520        }
    44894521        }
    44904522      }
     
    45004532    /* Handle special forms of bracket, which all start (? */
    45014533
    4502     if (ptr[1] == '?')
     4534    if (ptr + 1 < patternEnd && ptr[1] == '?')
    45034535      {
    45044536      int set, unset;
    45054537      int *optset;
    45064538
    4507       switch (c = ptr[2])
     4539      switch (c = (ptr + 2 < patternEnd ? ptr[2] : 0))
    45084540        {
    45094541        /* Skip over comments entirely */
    45104542        case '#':
    45114543        ptr += 3;
    4512         while (*ptr != 0 && *ptr != ')') ptr++;
    4513         if (*ptr == 0)
     4544        while (ptr < patternEnd && *ptr != ')')
     4545            ptr++;
     4546        if (ptr == patternEnd)
    45144547          {
    45154548          errorcode = ERR18;
     
    45474580          {
    45484581          ++ptr;
    4549           while ((DIGITAB(*ptr) & ctype_digit) != 0)
     4582          while (ptr < patternEnd && (DIGITAB(*ptr) & ctype_digit) != 0)
    45504583            ++ptr;
    45514584          }
    4552         if (*ptr != ')')
     4585        if (ptr >= patternEnd || *ptr != ')')
    45534586          {
    45544587          errorcode = ERR29;
     
    45614594        code that handles this for real brackets. */
    45624595
    4563         if (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{')
     4596        if (ptr + 1 < patternEnd && (ptr[1] == '+' || ptr[1] == '*' || ptr[1] == '?' || ptr[1] == '{'))
    45644597          {
    45654598          length += 2 + 2 * LINK_SIZE;       /* to make bracketed */
     
    45754608        case 'C':
    45764609        ptr += 3;
    4577         while ((DIGITAB(*ptr) & ctype_digit) != 0)
     4610        while (ptr < patternEnd && (DIGITAB(*ptr) & ctype_digit) != 0)
    45784611          ++ptr;
    4579         if (*ptr != ')')
     4612        if (ptr >= patternEnd || *ptr != ')')
    45804613          {
    45814614          errorcode = ERR39;
     
    45924625        /* Handle the definition of a named subpattern */
    45934626
    4594         if (*ptr == '<')
    4595           {
    4596           const pcre_uchar *p;    /* Don't amalgamate; some compilers */
    4597           p = ++ptr;          /* grumble at autoincrement in declaration */
    4598           while ((CTYPES(&compile_block, *ptr) & ctype_word) != 0) ptr++;
    4599           if (*ptr != '>')
    4600             {
    4601             errorcode = ERR42;
    4602             goto PCRE_ERROR_RETURN;
    4603             }
    4604           name_count++;
    4605           if (ptr - p > max_name_size) max_name_size = INT_CAST(ptr - p);
    4606           capturing = TRUE;   /* Named parentheses are always capturing */
    4607           break;
    4608           }
    4609 
    4610         /* Handle back references and recursive calls to named subpatterns */
    4611 
    4612         if (*ptr == '=' || *ptr == '>')
    4613           {
    4614           ++ptr;
    4615           while ((CTYPES(&compile_block, *ptr) & ctype_word) != 0)
    4616             ++ptr;
    4617           if (*ptr != ')')
    4618             {
    4619             errorcode = ERR42;
    4620             goto PCRE_ERROR_RETURN;
    4621             }
    4622           break;
    4623           }
     4627        if (ptr < patternEnd) {
     4628            if (*ptr == '<')
     4629              {
     4630              const pcre_uchar *p;    /* Don't amalgamate; some compilers */
     4631              p = ++ptr;          /* grumble at autoincrement in declaration */
     4632              while (ptr < patternEnd && (CTYPES(&compile_block, *ptr) & ctype_word) != 0)
     4633                  ptr++;
     4634              if (ptr >= patternEnd || *ptr != '>')
     4635                {
     4636                errorcode = ERR42;
     4637                goto PCRE_ERROR_RETURN;
     4638                }
     4639              name_count++;
     4640              if (ptr - p > max_name_size) max_name_size = INT_CAST(ptr - p);
     4641              capturing = TRUE;   /* Named parentheses are always capturing */
     4642              break;
     4643              }
     4644
     4645            /* Handle back references and recursive calls to named subpatterns */
     4646
     4647            if (*ptr == '=' || *ptr == '>')
     4648              {
     4649              ++ptr;
     4650              while (ptr < patternEnd && (CTYPES(&compile_block, *ptr) & ctype_word) != 0)
     4651                ++ptr;
     4652              if (ptr >= patternEnd || *ptr != ')')
     4653                {
     4654                errorcode = ERR42;
     4655                goto PCRE_ERROR_RETURN;
     4656                }
     4657              break;
     4658              }
     4659        }
    46244660
    46254661        /* Unknown character after (?P */
     
    46324668        case '<':
    46334669        ptr += 3;
    4634         if (*ptr == '=' || *ptr == '!')
     4670        if (ptr < patternEnd && (*ptr == '=' || *ptr == '!'))
    46354671          {
    46364672          branch_newextra = 1 + LINK_SIZE;
     
    46464682
    46474683        case '(':
    4648         if (ptr[3] == 'R' && ptr[4] == ')')
     4684        if (ptr + 4 < patternEnd && ptr[3] == 'R' && ptr[4] == ')')
    46494685          {
    46504686          ptr += 4;
    46514687          length += 3;
    46524688          }
    4653         else if ((DIGITAB(ptr[3]) & ctype_digit) != 0)
     4689        else if (ptr + 3 < patternEnd && (DIGITAB(ptr[3]) & ctype_digit) != 0)
    46544690          {
    46554691          ptr += 4;
    46564692          length += 3;
    4657           while ((DIGITAB(*ptr) & ctype_digit) != 0) ptr++;
    4658           if (*ptr != ')')
     4693          while (ptr < patternEnd && (DIGITAB(*ptr) & ctype_digit) != 0)
     4694              ptr++;
     4695          if (ptr >= patternEnd || *ptr != ')')
    46594696            {
    46604697            errorcode = ERR26;
     
    46654702          {
    46664703          ptr++;   /* Can treat like ':' as far as spacing is concerned */
    4667           if (ptr[2] != '?' ||
     4704          if (ptr + 3 >= patternEnd || ptr[2] != '?' ||
    46684705             (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
    46694706            {
     
    46874724        for (;; ptr++)
    46884725          {
    4689           c = *ptr;
     4726          c = ptr < patternEnd ? *ptr : 0;
    46904727          switch (c)
    46914728            {
     
    48614898    automatically; for the others we need an increment. */
    48624899
    4863     if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2))
     4900    if (ptr + 1 < patternEnd && (c = ptr[1]) == '{' && is_counted_repeat(ptr+2, patternEnd))
    48644901      {
    48654902      ptr = read_repeat_counts(ptr+2, &min, &max, &errorcode);
     
    48984935    /* Allow space for once brackets for "possessive quantifier" */
    48994936
    4900     if (ptr[1] == '+')
     4937    if (ptr + 1 < patternEnd && ptr[1] == '+')
    49014938      {
    49024939      ptr++;
     
    49124949    NORMAL_CHAR:
    49134950
    4914     if (inescq && c == '\\' && ptr[1] == 'E')
     4951    if (inescq && c == '\\' && ptr + 1 < patternEnd && ptr[1] == 'E')
    49154952      {
    49164953      inescq = FALSE;
     
    49294966        if (IS_LEADING_SURROGATE(c))
    49304967          {
    4931           c = DECODE_SURROGATE_PAIR(c, *ptr);
     4968          c = DECODE_SURROGATE_PAIR(c, ptr < patternEnd ? *ptr : 0);
    49324969          ++ptr;
    49334970          }
     
    49454982    if (utf8 && (c & 0xc0) == 0xc0)
    49464983      {
    4947       while ((ptr[1] & 0xc0) == 0x80)         /* Can't flow over the end */
     4984      while (ptr + 1 < patternEnd && (ptr[1] & 0xc0) == 0x80)         /* Can't flow over the end */
    49484985        {                                     /* because the end is marked */
    49494986        lastitemlength++;                     /* by a zero byte. */
     
    50185055*code = OP_BRA;
    50195056bracount = 0;
    5020 (void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr,
     5057(void)compile_regex(options, options & PCRE_IMS, &bracount, &code, &ptr, patternEnd,
    50215058  &errorcode, FALSE, 0, &firstbyte, &reqbyte, NULL, &compile_block);
    50225059re->top_bracket = bracount;
     
    50275064/* If not reached end of pattern on success, there's an excess bracket. */
    50285065
    5029 if (errorcode == 0 && *ptr != 0) errorcode = ERR22;
     5066if (errorcode == 0 && ptr < patternEnd) errorcode = ERR22;
    50305067
    50315068/* Fill in the terminating state and check for disastrous overflow, but
Note: See TracChangeset for help on using the changeset viewer.