Karsten Hopp ae9212
To: vim-dev@vim.org
Karsten Hopp ae9212
Subject: patch 7.0.183
Karsten Hopp ae9212
Fcc: outbox
Karsten Hopp ae9212
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp ae9212
Mime-Version: 1.0
Karsten Hopp ae9212
Content-Type: text/plain; charset=ISO-8859-1
Karsten Hopp ae9212
Content-Transfer-Encoding: 8bit
Karsten Hopp ae9212
------------
Karsten Hopp ae9212
Karsten Hopp ae9212
Patch 7.0.183
Karsten Hopp ae9212
Problem:    Crash in ":let" when redirecting to a variable that's being
Karsten Hopp ae9212
	    displayed. (Thomas Link)
Karsten Hopp ae9212
Solution:   When redirecting to a variable only do the assignment when
Karsten Hopp ae9212
	    stopping redirection to avoid that setting the variable causes a
Karsten Hopp ae9212
	    freed string to be accessed.
Karsten Hopp ae9212
Files:	    src/eval.c
Karsten Hopp ae9212
Karsten Hopp ae9212
Karsten Hopp ae9212
*** ../vim-7.0.182/src/eval.c	Tue Dec  5 10:33:57 2006
Karsten Hopp ae9212
--- src/eval.c	Sun Jan 14 14:20:49 2007
Karsten Hopp ae9212
***************
Karsten Hopp ae9212
*** 898,903 ****
Karsten Hopp ae9212
--- 898,904 ----
Karsten Hopp ae9212
  }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
  static lval_T	*redir_lval = NULL;
Karsten Hopp ae9212
+ static garray_T redir_ga;	/* only valid when redir_lval is not NULL */
Karsten Hopp ae9212
  static char_u	*redir_endp = NULL;
Karsten Hopp ae9212
  static char_u	*redir_varname = NULL;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
***************
Karsten Hopp ae9212
*** 932,937 ****
Karsten Hopp ae9212
--- 933,941 ----
Karsten Hopp ae9212
  	return FAIL;
Karsten Hopp ae9212
      }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
+     /* The output is stored in growarray "redir_ga" until redirection ends. */
Karsten Hopp ae9212
+     ga_init2(&redir_ga, (int)sizeof(char), 500);
Karsten Hopp ae9212
+ 
Karsten Hopp ae9212
      /* Parse the variable name (can be a dict or list entry). */
Karsten Hopp ae9212
      redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
Karsten Hopp ae9212
  							     FNE_CHECK_START);
Karsten Hopp ae9212
***************
Karsten Hopp ae9212
*** 974,1015 ****
Karsten Hopp ae9212
  }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
  /*
Karsten Hopp ae9212
!  * Append "value[len]" to the variable set by var_redir_start().
Karsten Hopp ae9212
   */
Karsten Hopp ae9212
      void
Karsten Hopp ae9212
! var_redir_str(value, len)
Karsten Hopp ae9212
      char_u	*value;
Karsten Hopp ae9212
!     int		len;
Karsten Hopp ae9212
  {
Karsten Hopp ae9212
!     char_u	*val;
Karsten Hopp ae9212
!     typval_T	tv;
Karsten Hopp ae9212
!     int		save_emsg;
Karsten Hopp ae9212
!     int		err;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
      if (redir_lval == NULL)
Karsten Hopp ae9212
  	return;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
!     if (len == -1)
Karsten Hopp ae9212
! 	/* Append the entire string */
Karsten Hopp ae9212
! 	val = vim_strsave(value);
Karsten Hopp ae9212
!     else
Karsten Hopp ae9212
! 	/* Append only the specified number of characters */
Karsten Hopp ae9212
! 	val = vim_strnsave(value, len);
Karsten Hopp ae9212
!     if (val == NULL)
Karsten Hopp ae9212
! 	return;
Karsten Hopp ae9212
! 
Karsten Hopp ae9212
!     tv.v_type = VAR_STRING;
Karsten Hopp ae9212
!     tv.vval.v_string = val;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
!     save_emsg = did_emsg;
Karsten Hopp ae9212
!     did_emsg = FALSE;
Karsten Hopp ae9212
!     set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
Karsten Hopp ae9212
!     err = did_emsg;
Karsten Hopp ae9212
!     did_emsg |= save_emsg;
Karsten Hopp ae9212
!     if (err)
Karsten Hopp ae9212
  	var_redir_stop();
Karsten Hopp ae9212
- 
Karsten Hopp ae9212
-     vim_free(tv.vval.v_string);
Karsten Hopp ae9212
  }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
  /*
Karsten Hopp ae9212
--- 978,1013 ----
Karsten Hopp ae9212
  }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
  /*
Karsten Hopp ae9212
!  * Append "value[value_len]" to the variable set by var_redir_start().
Karsten Hopp ae9212
!  * The actual appending is postponed until redirection ends, because the value
Karsten Hopp ae9212
!  * appended may in fact be the string we write to, changing it may cause freed
Karsten Hopp ae9212
!  * memory to be used:
Karsten Hopp ae9212
!  *   :redir => foo
Karsten Hopp ae9212
!  *   :let foo
Karsten Hopp ae9212
!  *   :redir END
Karsten Hopp ae9212
   */
Karsten Hopp ae9212
      void
Karsten Hopp ae9212
! var_redir_str(value, value_len)
Karsten Hopp ae9212
      char_u	*value;
Karsten Hopp ae9212
!     int		value_len;
Karsten Hopp ae9212
  {
Karsten Hopp ae9212
!     size_t	len;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
      if (redir_lval == NULL)
Karsten Hopp ae9212
  	return;
Karsten Hopp ae9212
  
Karsten Hopp ae9212
!     if (value_len == -1)
Karsten Hopp ae9212
! 	len = STRLEN(value);	/* Append the entire string */
Karsten Hopp ae9212
!     else
Karsten Hopp ae9212
! 	len = value_len;	/* Append only "value_len" characters */
Karsten Hopp ae9212
  
Karsten Hopp ae9212
!     if (ga_grow(&redir_ga, (int)len) == OK)
Karsten Hopp ae9212
!     {
Karsten Hopp ae9212
! 	mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
Karsten Hopp ae9212
! 	redir_ga.ga_len += len;
Karsten Hopp ae9212
!     }
Karsten Hopp ae9212
!     else
Karsten Hopp ae9212
  	var_redir_stop();
Karsten Hopp ae9212
  }
Karsten Hopp ae9212
  
Karsten Hopp ae9212
  /*
Karsten Hopp ae9212
***************
Karsten Hopp ae9212
*** 1018,1025 ****
Karsten Hopp ae9212
--- 1016,1034 ----
Karsten Hopp ae9212
      void
Karsten Hopp ae9212
  var_redir_stop()
Karsten Hopp ae9212
  {
Karsten Hopp ae9212
+     typval_T	tv;
Karsten Hopp ae9212
+ 
Karsten Hopp ae9212
      if (redir_lval != NULL)
Karsten Hopp ae9212
      {
Karsten Hopp ae9212
+ 	/* Append the trailing NUL. */
Karsten Hopp ae9212
+ 	ga_append(&redir_ga, NUL);
Karsten Hopp ae9212
+ 
Karsten Hopp ae9212
+ 	/* Assign the text to the variable. */
Karsten Hopp ae9212
+ 	tv.v_type = VAR_STRING;
Karsten Hopp ae9212
+ 	tv.vval.v_string = redir_ga.ga_data;
Karsten Hopp ae9212
+ 	set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
Karsten Hopp ae9212
+ 	vim_free(tv.vval.v_string);
Karsten Hopp ae9212
+ 
Karsten Hopp ae9212
  	clear_lval(redir_lval);
Karsten Hopp ae9212
  	vim_free(redir_lval);
Karsten Hopp ae9212
  	redir_lval = NULL;
Karsten Hopp ae9212
*** ../vim-7.0.182/src/version.c	Tue Jan  9 20:29:55 2007
Karsten Hopp ae9212
--- src/version.c	Sun Jan 14 15:23:23 2007
Karsten Hopp ae9212
***************
Karsten Hopp ae9212
*** 668,669 ****
Karsten Hopp ae9212
--- 668,671 ----
Karsten Hopp ae9212
  {   /* Add new patch number below this line */
Karsten Hopp ae9212
+ /**/
Karsten Hopp ae9212
+     183,
Karsten Hopp ae9212
  /**/
Karsten Hopp ae9212
Karsten Hopp ae9212
-- 
Karsten Hopp ae9212
How To Keep A Healthy Level Of Insanity:
Karsten Hopp ae9212
16. Have your coworkers address you by your wrestling name, Rock Hard Kim.
Karsten Hopp ae9212
Karsten Hopp ae9212
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp ae9212
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp ae9212
\\\        download, build and distribute -- http://www.A-A-P.org        ///
Karsten Hopp ae9212
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///