/[pcre]/code/trunk/pcre_compile.c
ViewVC logotype

Diff of /code/trunk/pcre_compile.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1347 by ph10, Fri May 10 14:03:18 2013 UTC revision 1348 by ph10, Fri Jul 5 10:38:37 2013 UTC
# Line 2353  Arguments: Line 2353  Arguments:
2353    endcode     points to where to stop    endcode     points to where to stop
2354    utf         TRUE if in UTF-8 / UTF-16 / UTF-32 mode    utf         TRUE if in UTF-8 / UTF-16 / UTF-32 mode
2355    cd          contains pointers to tables etc.    cd          contains pointers to tables etc.
2356      recurses    chain of recurse_check to catch mutual recursion
2357    
2358  Returns:      TRUE if what is matched could be empty  Returns:      TRUE if what is matched could be empty
2359  */  */
2360    
2361    typedef struct recurse_check {
2362      struct recurse_check *prev;
2363      const pcre_uchar *group;
2364    } recurse_check;
2365    
2366  static BOOL  static BOOL
2367  could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,  could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
2368    BOOL utf, compile_data *cd)    BOOL utf, compile_data *cd, recurse_check *recurses)
2369  {  {
2370  register pcre_uchar c;  register pcre_uchar c;
2371    recurse_check this_recurse;
2372    
2373  for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);  for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
2374       code < endcode;       code < endcode;
2375       code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE))       code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE))
# Line 2369  for (code = first_significant_code(code Line 2377  for (code = first_significant_code(code
2377    const pcre_uchar *ccode;    const pcre_uchar *ccode;
2378    
2379    c = *code;    c = *code;
2380    
2381    /* Skip over forward assertions; the other assertions are skipped by    /* Skip over forward assertions; the other assertions are skipped by
2382    first_significant_code() with a TRUE final argument. */    first_significant_code() with a TRUE final argument. */
2383    
# Line 2389  for (code = first_significant_code(code Line 2397  for (code = first_significant_code(code
2397    
2398    if (c == OP_RECURSE)    if (c == OP_RECURSE)
2399      {      {
2400      const pcre_uchar *scode;      const pcre_uchar *scode = cd->start_code + GET(code, 1);
2401      BOOL empty_branch;      BOOL empty_branch;
2402    
2403      /* Test for forward reference */      /* Test for forward reference or uncompleted reference. This is disabled
2404        when called to scan a completed pattern by setting cd->start_workspace to
2405      for (scode = cd->start_workspace; scode < cd->hwm; scode += LINK_SIZE)      NULL. */
2406        if ((int)GET(scode, 0) == (int)(code + 1 - cd->start_code)) return TRUE;  
2407        if (cd->start_workspace != NULL)
2408          {
2409          const pcre_uchar *tcode;
2410          for (tcode = cd->start_workspace; tcode < cd->hwm; tcode += LINK_SIZE)
2411            if ((int)GET(tcode, 0) == (int)(code + 1 - cd->start_code)) return TRUE;
2412          if (GET(scode, 1) == 0) return TRUE;    /* Unclosed */
2413          }
2414    
2415        /* If we are scanning a completed pattern, there are no forward references
2416        and all groups are complete. We need to detect whether this is a recursive
2417        call, as otherwise there will be an infinite loop. If it is a recursion,
2418        just skip over it. Simple recursions are easily detected. For mutual
2419        recursions we keep a chain on the stack. */
2420    
2421        else
2422          {
2423          recurse_check *r = recurses;
2424          const pcre_uchar *endgroup = scode;
2425    
2426          do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
2427          if (code >= scode && code <= endgroup) continue;  /* Simple recursion */
2428    
2429          for (r = recurses; r != NULL; r = r->prev)
2430            if (r->group == scode) break;
2431          if (r != NULL) continue;   /* Mutual recursion */
2432          }
2433    
2434      /* Not a forward reference, test for completed backward reference */      /* Completed reference; scan the referenced group, remembering it on the
2435        stack chain to detect mutual recursions. */
2436    
2437      empty_branch = FALSE;      empty_branch = FALSE;
2438      scode = cd->start_code + GET(code, 1);      this_recurse.prev = recurses;
2439      if (GET(scode, 1) == 0) return TRUE;    /* Unclosed */      this_recurse.group = scode;
2440    
     /* Completed backwards reference */  
   
2441      do      do
2442        {        {
2443        if (could_be_empty_branch(scode, endcode, utf, cd))        if (could_be_empty_branch(scode, endcode, utf, cd, &this_recurse))
2444          {          {
2445          empty_branch = TRUE;          empty_branch = TRUE;
2446          break;          break;
# Line 2463  for (code = first_significant_code(code Line 2496  for (code = first_significant_code(code
2496        empty_branch = FALSE;        empty_branch = FALSE;
2497        do        do
2498          {          {
2499          if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd))          if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, NULL))
2500            empty_branch = TRUE;            empty_branch = TRUE;
2501          code += GET(code, 1);          code += GET(code, 1);
2502          }          }
# Line 2521  for (code = first_significant_code(code Line 2554  for (code = first_significant_code(code
2554    
2555      /* Opcodes that must match a character */      /* Opcodes that must match a character */
2556    
2557        case OP_ANY:
2558        case OP_ALLANY:
2559        case OP_ANYBYTE:
2560    
2561      case OP_PROP:      case OP_PROP:
2562      case OP_NOTPROP:      case OP_NOTPROP:
2563        case OP_ANYNL:
2564    
2565        case OP_NOT_HSPACE:
2566        case OP_HSPACE:
2567        case OP_NOT_VSPACE:
2568        case OP_VSPACE:
2569      case OP_EXTUNI:      case OP_EXTUNI:
2570    
2571      case OP_NOT_DIGIT:      case OP_NOT_DIGIT:
2572      case OP_DIGIT:      case OP_DIGIT:
2573      case OP_NOT_WHITESPACE:      case OP_NOT_WHITESPACE:
2574      case OP_WHITESPACE:      case OP_WHITESPACE:
2575      case OP_NOT_WORDCHAR:      case OP_NOT_WORDCHAR:
2576      case OP_WORDCHAR:      case OP_WORDCHAR:
2577      case OP_ANY:  
     case OP_ALLANY:  
     case OP_ANYBYTE:  
2578      case OP_CHAR:      case OP_CHAR:
2579      case OP_CHARI:      case OP_CHARI:
2580      case OP_NOT:      case OP_NOT:
2581      case OP_NOTI:      case OP_NOTI:
2582    
2583      case OP_PLUS:      case OP_PLUS:
2584        case OP_PLUSI:
2585      case OP_MINPLUS:      case OP_MINPLUS:
2586      case OP_POSPLUS:      case OP_MINPLUSI:
2587      case OP_EXACT:  
2588      case OP_NOTPLUS:      case OP_NOTPLUS:
2589        case OP_NOTPLUSI:
2590      case OP_NOTMINPLUS:      case OP_NOTMINPLUS:
2591        case OP_NOTMINPLUSI:
2592    
2593        case OP_POSPLUS:
2594        case OP_POSPLUSI:
2595      case OP_NOTPOSPLUS:      case OP_NOTPOSPLUS:
2596        case OP_NOTPOSPLUSI:
2597    
2598        case OP_EXACT:
2599        case OP_EXACTI:
2600      case OP_NOTEXACT:      case OP_NOTEXACT:
2601        case OP_NOTEXACTI:
2602    
2603      case OP_TYPEPLUS:      case OP_TYPEPLUS:
2604      case OP_TYPEMINPLUS:      case OP_TYPEMINPLUS:
2605      case OP_TYPEPOSPLUS:      case OP_TYPEPOSPLUS:
2606      case OP_TYPEEXACT:      case OP_TYPEEXACT:
2607    
2608      return FALSE;      return FALSE;
2609    
2610      /* These are going to continue, as they may be empty, but we have to      /* These are going to continue, as they may be empty, but we have to
# Line 2582  for (code = first_significant_code(code Line 2638  for (code = first_significant_code(code
2638      return TRUE;      return TRUE;
2639    
2640      /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,      /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,
2641      MINUPTO, and POSUPTO may be followed by a multibyte character */      MINUPTO, and POSUPTO and their caseless and negative versions may be
2642        followed by a multibyte character. */
2643    
2644  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32  #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2645      case OP_STAR:      case OP_STAR:
2646      case OP_STARI:      case OP_STARI:
2647        case OP_NOTSTAR:
2648        case OP_NOTSTARI:
2649    
2650      case OP_MINSTAR:      case OP_MINSTAR:
2651      case OP_MINSTARI:      case OP_MINSTARI:
2652        case OP_NOTMINSTAR:
2653        case OP_NOTMINSTARI:
2654    
2655      case OP_POSSTAR:      case OP_POSSTAR:
2656      case OP_POSSTARI:      case OP_POSSTARI:
2657        case OP_NOTPOSSTAR:
2658        case OP_NOTPOSSTARI:
2659    
2660      case OP_QUERY:      case OP_QUERY:
2661      case OP_QUERYI:      case OP_QUERYI:
2662        case OP_NOTQUERY:
2663        case OP_NOTQUERYI:
2664    
2665      case OP_MINQUERY:      case OP_MINQUERY:
2666      case OP_MINQUERYI:      case OP_MINQUERYI:
2667        case OP_NOTMINQUERY:
2668        case OP_NOTMINQUERYI:
2669    
2670      case OP_POSQUERY:      case OP_POSQUERY:
2671      case OP_POSQUERYI:      case OP_POSQUERYI:
2672        case OP_NOTPOSQUERY:
2673        case OP_NOTPOSQUERYI:
2674    
2675      if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);      if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
2676      break;      break;
2677    
2678      case OP_UPTO:      case OP_UPTO:
2679      case OP_UPTOI:      case OP_UPTOI:
2680        case OP_NOTUPTO:
2681        case OP_NOTUPTOI:
2682    
2683      case OP_MINUPTO:      case OP_MINUPTO:
2684      case OP_MINUPTOI:      case OP_MINUPTOI:
2685        case OP_NOTMINUPTO:
2686        case OP_NOTMINUPTOI:
2687    
2688      case OP_POSUPTO:      case OP_POSUPTO:
2689      case OP_POSUPTOI:      case OP_POSUPTOI:
2690        case OP_NOTPOSUPTO:
2691        case OP_NOTPOSUPTOI:
2692    
2693      if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);      if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);
2694      break;      break;
2695  #endif  #endif
# Line 2659  could_be_empty(const pcre_uchar *code, c Line 2743  could_be_empty(const pcre_uchar *code, c
2743  {  {
2744  while (bcptr != NULL && bcptr->current_branch >= code)  while (bcptr != NULL && bcptr->current_branch >= code)
2745    {    {
2746    if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd))    if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd, NULL))
2747      return FALSE;      return FALSE;
2748    bcptr = bcptr->outer;    bcptr = bcptr->outer;
2749    }    }
# Line 5391  for (;; ptr++) Line 5475  for (;; ptr++)
5475              pcre_uchar *scode = bracode;              pcre_uchar *scode = bracode;
5476              do              do
5477                {                {
5478                if (could_be_empty_branch(scode, ketcode, utf, cd))                if (could_be_empty_branch(scode, ketcode, utf, cd, NULL))
5479                  {                  {
5480                  *bracode += OP_SBRA - OP_BRA;                  *bracode += OP_SBRA - OP_BRA;
5481                  break;                  break;
# Line 8213  if (cd->hwm > cd->start_workspace) Line 8297  if (cd->hwm > cd->start_workspace)
8297      }      }
8298    }    }
8299    
8300  /* If the workspace had to be expanded, free the new memory. */  /* If the workspace had to be expanded, free the new memory. Set the pointer to
8301    NULL to indicate that forward references have been filled in. */
8302    
8303  if (cd->workspace_size > COMPILE_WORK_SIZE)  if (cd->workspace_size > COMPILE_WORK_SIZE)
8304    (PUBL(free))((void *)cd->start_workspace);    (PUBL(free))((void *)cd->start_workspace);
8305    cd->start_workspace = NULL;
8306    
8307  /* Give an error if there's back reference to a non-existent capturing  /* Give an error if there's back reference to a non-existent capturing
8308  subpattern. */  subpattern. */
# Line 8420  if (code - codestart > length) Line 8506  if (code - codestart > length)
8506    }    }
8507  #endif   /* PCRE_DEBUG */  #endif   /* PCRE_DEBUG */
8508    
8509    /* Check for a pattern than can match an empty string, so that this information
8510    can be provided to applications. */
8511    
8512    do
8513      {
8514      if (could_be_empty_branch(codestart, code, utf, cd, NULL))
8515        {
8516        re->flags |= PCRE_MATCH_EMPTY;
8517        break;
8518        }
8519      codestart += GET(codestart, 1);
8520      }
8521    while (*codestart == OP_ALT);
8522    
8523  #if defined COMPILE_PCRE8  #if defined COMPILE_PCRE8
8524  return (pcre *)re;  return (pcre *)re;
8525  #elif defined COMPILE_PCRE16  #elif defined COMPILE_PCRE16

Legend:
Removed from v.1347  
changed lines
  Added in v.1348

  ViewVC Help
Powered by ViewVC 1.1.5