1cb0574
To: vim-dev@vim.org
1cb0574
Subject: Patch 7.2.307
1cb0574
Fcc: outbox
1cb0574
From: Bram Moolenaar <Bram@moolenaar.net>
1cb0574
Mime-Version: 1.0
1cb0574
Content-Type: text/plain; charset=UTF-8
1cb0574
Content-Transfer-Encoding: 8bit
1cb0574
------------
1cb0574
1cb0574
Patch 7.2.307
1cb0574
Problem:    Crash with a very long syntax match statement. (Guy Gur Ari)
1cb0574
Solution:   When the offset does not fit in the two bytes available give an
1cb0574
            error instead of continuing with invalid pointers.
1cb0574
Files:      src/regexp.c
1cb0574
1cb0574
1cb0574
*** ../vim-7.2.306/src/regexp.c	2009-05-15 21:31:11.000000000 +0200
1cb0574
--- src/regexp.c	2009-11-25 18:13:03.000000000 +0100
1cb0574
***************
1cb0574
*** 583,588 ****
1cb0574
--- 583,589 ----
1cb0574
  #endif
1cb0574
  static char_u	*regcode;	/* Code-emit pointer, or JUST_CALC_SIZE */
1cb0574
  static long	regsize;	/* Code size. */
1cb0574
+ static int	reg_toolong;	/* TRUE when offset out of range */
1cb0574
  static char_u	had_endbrace[NSUBEXP];	/* flags, TRUE if end of () found */
1cb0574
  static unsigned	regflags;	/* RF_ flags for prog */
1cb0574
  static long	brace_min[10];	/* Minimums for complex brace repeats */
1cb0574
***************
1cb0574
*** 1028,1036 ****
1cb0574
      regcomp_start(expr, re_flags);
1cb0574
      regcode = r->program;
1cb0574
      regc(REGMAGIC);
1cb0574
!     if (reg(REG_NOPAREN, &flags) == NULL)
1cb0574
      {
1cb0574
  	vim_free(r);
1cb0574
  	return NULL;
1cb0574
      }
1cb0574
  
1cb0574
--- 1029,1039 ----
1cb0574
      regcomp_start(expr, re_flags);
1cb0574
      regcode = r->program;
1cb0574
      regc(REGMAGIC);
1cb0574
!     if (reg(REG_NOPAREN, &flags) == NULL || reg_toolong)
1cb0574
      {
1cb0574
  	vim_free(r);
1cb0574
+ 	if (reg_toolong)
1cb0574
+ 	    EMSG_RET_NULL(_("E339: Pattern too long"));
1cb0574
  	return NULL;
1cb0574
      }
1cb0574
  
1cb0574
***************
1cb0574
*** 1141,1146 ****
1cb0574
--- 1144,1150 ----
1cb0574
      re_has_z = 0;
1cb0574
  #endif
1cb0574
      regsize = 0L;
1cb0574
+     reg_toolong = FALSE;
1cb0574
      regflags = 0;
1cb0574
  #if defined(FEAT_SYN_HL) || defined(PROTO)
1cb0574
      had_eol = FALSE;
1cb0574
***************
1cb0574
*** 1228,1234 ****
1cb0574
      {
1cb0574
  	skipchr();
1cb0574
  	br = regbranch(&flags);
1cb0574
! 	if (br == NULL)
1cb0574
  	    return NULL;
1cb0574
  	regtail(ret, br);	/* BRANCH -> BRANCH. */
1cb0574
  	if (!(flags & HASWIDTH))
1cb0574
--- 1232,1238 ----
1cb0574
      {
1cb0574
  	skipchr();
1cb0574
  	br = regbranch(&flags);
1cb0574
! 	if (br == NULL || reg_toolong)
1cb0574
  	    return NULL;
1cb0574
  	regtail(ret, br);	/* BRANCH -> BRANCH. */
1cb0574
  	if (!(flags & HASWIDTH))
1cb0574
***************
1cb0574
*** 1313,1318 ****
1cb0574
--- 1317,1324 ----
1cb0574
  	    break;
1cb0574
  	skipchr();
1cb0574
  	regtail(latest, regnode(END)); /* operand ends */
1cb0574
+ 	if (reg_toolong)
1cb0574
+ 	    break;
1cb0574
  	reginsert(MATCH, latest);
1cb0574
  	chain = latest;
1cb0574
      }
1cb0574
***************
1cb0574
*** 1382,1388 ****
1cb0574
  			    break;
1cb0574
  	    default:
1cb0574
  			    latest = regpiece(&flags);
1cb0574
! 			    if (latest == NULL)
1cb0574
  				return NULL;
1cb0574
  			    *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH);
1cb0574
  			    if (chain == NULL)	/* First piece. */
1cb0574
--- 1388,1394 ----
1cb0574
  			    break;
1cb0574
  	    default:
1cb0574
  			    latest = regpiece(&flags);
1cb0574
! 			    if (latest == NULL || reg_toolong)
1cb0574
  				return NULL;
1cb0574
  			    *flagp |= flags & (HASWIDTH | HASNL | HASLOOKBH);
1cb0574
  			    if (chain == NULL)	/* First piece. */
1cb0574
***************
1cb0574
*** 2540,2547 ****
1cb0574
  	offset = (int)(scan - val);
1cb0574
      else
1cb0574
  	offset = (int)(val - scan);
1cb0574
!     *(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377);
1cb0574
!     *(scan + 2) = (char_u) (offset & 0377);
1cb0574
  }
1cb0574
  
1cb0574
  /*
1cb0574
--- 2546,2561 ----
1cb0574
  	offset = (int)(scan - val);
1cb0574
      else
1cb0574
  	offset = (int)(val - scan);
1cb0574
!     /* When the offset uses more than 16 bits it can no longer fit in the two
1cb0574
!      * bytes avaliable.  Use a global flag to avoid having to check return
1cb0574
!      * values in too many places. */
1cb0574
!     if (offset > 0xffff)
1cb0574
! 	reg_toolong = TRUE;
1cb0574
!     else
1cb0574
!     {
1cb0574
! 	*(scan + 1) = (char_u) (((unsigned)offset >> 8) & 0377);
1cb0574
! 	*(scan + 2) = (char_u) (offset & 0377);
1cb0574
!     }
1cb0574
  }
1cb0574
  
1cb0574
  /*
1cb0574
***************
1cb0574
*** 5764,5769 ****
1cb0574
--- 5778,5785 ----
1cb0574
  
1cb0574
  /*
1cb0574
   * regnext - dig the "next" pointer out of a node
1cb0574
+  * Returns NULL when calculating size, when there is no next item and when
1cb0574
+  * there is an error.
1cb0574
   */
1cb0574
      static char_u *
1cb0574
  regnext(p)
1cb0574
***************
1cb0574
*** 5771,5777 ****
1cb0574
  {
1cb0574
      int	    offset;
1cb0574
  
1cb0574
!     if (p == JUST_CALC_SIZE)
1cb0574
  	return NULL;
1cb0574
  
1cb0574
      offset = NEXT(p);
1cb0574
--- 5787,5793 ----
1cb0574
  {
1cb0574
      int	    offset;
1cb0574
  
1cb0574
!     if (p == JUST_CALC_SIZE || reg_toolong)
1cb0574
  	return NULL;
1cb0574
  
1cb0574
      offset = NEXT(p);
1cb0574
*** ../vim-7.2.306/src/version.c	2009-11-25 17:15:16.000000000 +0100
1cb0574
--- src/version.c	2009-11-25 18:14:32.000000000 +0100
1cb0574
***************
1cb0574
*** 683,684 ****
1cb0574
--- 683,686 ----
1cb0574
  {   /* Add new patch number below this line */
1cb0574
+ /**/
1cb0574
+     307,
1cb0574
  /**/
1cb0574
1cb0574
-- 
1cb0574
The fastest way to get an engineer to solve a problem is to declare that the
1cb0574
problem is unsolvable.  No engineer can walk away from an unsolvable problem
1cb0574
until it's solved.
1cb0574
				(Scott Adams - The Dilbert principle)
1cb0574
1cb0574
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
1cb0574
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
1cb0574
\\\        download, build and distribute -- http://www.A-A-P.org        ///
1cb0574
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///