Patch 7.2.307
Problem:    Crash with a very long syntax match statement. (Guy Gur Ari)
Solution:   When the offset does not fit in the two bytes available give an
            error instead of continuing with invalid pointers.
Files:      src/regexp.c


*** ../vim-7.2.306/src/regexp.c 2009-05-15 21:31:11.000000000 +0200
--- src/regexp.c        2009-11-25 18:13:03.000000000 +0100
***************
*** 583,588 ****
--- 583,589 ----
  #endif
  static char_u *regcode;       /* Code-emit pointer, or JUST_CALC_SIZE */
  static long   regsize;        /* Code size. */
+ static int    reg_toolong;    /* TRUE when offset out of range */
  static char_u had_endbrace[NSUBEXP];  /* flags, TRUE if end of () found */
  static unsigned       regflags;       /* RF_ flags for prog */
  static long   brace_min[10];  /* Minimums for complex brace repeats */
***************
*** 1028,1036 ****
      regcomp_start(expr, re_flags);
      regcode = r->program;
      regc(REGMAGIC);
!     if (reg(REG_NOPAREN, &flags) == NULL)
      {
        vim_free(r);
        return NULL;
      }
  
--- 1029,1039 ----
      regcomp_start(expr, re_flags);
      regcode = r->program;
      regc(REGMAGIC);
!     if (reg(REG_NOPAREN, &flags) == NULL || reg_toolong)
      {
        vim_free(r);
+       if (reg_toolong)
+           EMSG_RET_NULL(_("E339: Pattern too long"));
        return NULL;
      }
  
***************
*** 1141,1146 ****
--- 1144,1150 ----
      re_has_z = 0;
  #endif
      regsize = 0L;
+     reg_toolong = FALSE;
      regflags = 0;
  #if defined(FEAT_SYN_HL) || defined(PROTO)
      had_eol = FALSE;
***************
*** 1228,1234 ****
      {
        skipchr();
        br = regbranch(&flags);
!       if (br == NULL)
            return NULL;
        regtail(ret, br);       /* BRANCH -> BRANCH. */
        if (!(flags & HASWIDTH))
--- 1232,1238 ----
      {
        skipchr();
        br = regbranch(&flags);
!       if (br == NULL || reg_toolong)
            return NULL;
        regtail(ret, br);       /* BRANCH -> BRANCH. */
        if (!(flags & HASWIDTH))
***************
*** 1313,1318 ****
--- 1317,1324 ----
            break;
        skipchr();
        regtail(latest, regnode(END)); /* operand ends */
+       if (reg_toolong)
+           break;
        reginsert(MATCH, latest);
        chain = latest;
      }
***************
*** 1382,1388 ****
                            break;
            default:
                            latest = regpiece(&flags);
!                           if (latest == NULL)
                                return NULL;
                            *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH);
                            if (chain == NULL)  /* First piece. */
--- 1388,1394 ----
                            break;
            default:
                            latest = regpiece(&flags);
!                           if (latest == NULL || reg_toolong)
                                return NULL;
                            *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH);
                            if (chain == NULL)  /* First piece. */
***************
*** 2540,2547 ****
        offset = (int)(scan - val);
      else
        offset = (int)(val - scan);
!     *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377);
!     *(scan + 2) = (char_u) (offset & 0377);
  }
  
  /*
--- 2546,2561 ----
        offset = (int)(scan - val);
      else
        offset = (int)(val - scan);
!     /* When the offset uses more than 16 bits it can no longer fit in the two
!      * bytes avaliable.  Use a global flag to avoid having to check return
!      * values in too many places. */
!     if (offset > 0xffff)
!       reg_toolong = TRUE;
!     else
!     {
!       *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377);
!       *(scan + 2) = (char_u) (offset & 0377);
!     }
  }
  
  /*
***************
*** 5764,5769 ****
--- 5778,5785 ----
  
  /*
   * regnext - dig the "next" pointer out of a node
+  * Returns NULL when calculating size, when there is no next item and when
+  * there is an error.
   */
      static char_u *
  regnext(p)
***************
*** 5771,5777 ****
  {
      int           offset;
  
!     if (p == JUST_CALC_SIZE)
        return NULL;
  
      offset = NEXT(p);
--- 5787,5793 ----
  {
      int           offset;
  
!     if (p == JUST_CALC_SIZE || reg_toolong)
        return NULL;
  
      offset = NEXT(p);
*** ../vim-7.2.306/src/version.c        2009-11-25 17:15:16.000000000 +0100
--- src/version.c       2009-11-25 18:14:32.000000000 +0100
***************
*** 683,684 ****
--- 683,686 ----
  {   /* Add new patch number below this line */
+ /**/
+     307,
  /**/

-- 
The fastest way to get an engineer to solve a problem is to declare that the
problem is unsolvable.  No engineer can walk away from an unsolvable problem
until it's solved.
                                (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui