Karsten Hopp ffaccd
To: vim-dev@vim.org
Karsten Hopp ffaccd
Subject: Patch 7.2.440
Karsten Hopp ffaccd
Fcc: outbox
Karsten Hopp ffaccd
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp ffaccd
Mime-Version: 1.0
Karsten Hopp ffaccd
Content-Type: text/plain; charset=UTF-8
Karsten Hopp ffaccd
Content-Transfer-Encoding: 8bit
Karsten Hopp ffaccd
------------
Karsten Hopp ffaccd
Karsten Hopp ffaccd
Patch 7.2.440
Karsten Hopp ffaccd
Problem:    Calling a function through a funcref, where the function deletes
Karsten Hopp ffaccd
	    the funcref, leads to an invalid memory access.
Karsten Hopp ffaccd
Solution:   Make a copy of the function name. (Lech Lorens)
Karsten Hopp ffaccd
Files:	    src/eval.c, src/testdir/test34.in, src/testdir/test34.ok
Karsten Hopp ffaccd
Karsten Hopp ffaccd
Karsten Hopp ffaccd
*** ../vim-7.2.439/src/eval.c	2010-05-16 13:26:19.000000000 +0200
Karsten Hopp ffaccd
--- src/eval.c	2010-05-28 22:01:07.000000000 +0200
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 464,470 ****
Karsten Hopp ffaccd
  static int find_internal_func __ARGS((char_u *name));
Karsten Hopp ffaccd
  static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
Karsten Hopp ffaccd
  static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Karsten Hopp ffaccd
! static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Karsten Hopp ffaccd
  static void emsg_funcname __ARGS((char *ermsg, char_u *name));
Karsten Hopp ffaccd
  static int non_zero_arg __ARGS((typval_T *argvars));
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
--- 464,470 ----
Karsten Hopp ffaccd
  static int find_internal_func __ARGS((char_u *name));
Karsten Hopp ffaccd
  static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
Karsten Hopp ffaccd
  static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Karsten Hopp ffaccd
! static int call_func __ARGS((char_u *func_name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Karsten Hopp ffaccd
  static void emsg_funcname __ARGS((char *ermsg, char_u *name));
Karsten Hopp ffaccd
  static int non_zero_arg __ARGS((typval_T *argvars));
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 7997,8005 ****
Karsten Hopp ffaccd
   * Also returns OK when an error was encountered while executing the function.
Karsten Hopp ffaccd
   */
Karsten Hopp ffaccd
      static int
Karsten Hopp ffaccd
! call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Karsten Hopp ffaccd
  						doesrange, evaluate, selfdict)
Karsten Hopp ffaccd
!     char_u	*name;		/* name of the function */
Karsten Hopp ffaccd
      int		len;		/* length of "name" */
Karsten Hopp ffaccd
      typval_T	*rettv;		/* return value goes here */
Karsten Hopp ffaccd
      int		argcount;	/* number of "argvars" */
Karsten Hopp ffaccd
--- 7997,8005 ----
Karsten Hopp ffaccd
   * Also returns OK when an error was encountered while executing the function.
Karsten Hopp ffaccd
   */
Karsten Hopp ffaccd
      static int
Karsten Hopp ffaccd
! call_func(func_name, len, rettv, argcount, argvars, firstline, lastline,
Karsten Hopp ffaccd
  						doesrange, evaluate, selfdict)
Karsten Hopp ffaccd
!     char_u	*func_name;	/* name of the function */
Karsten Hopp ffaccd
      int		len;		/* length of "name" */
Karsten Hopp ffaccd
      typval_T	*rettv;		/* return value goes here */
Karsten Hopp ffaccd
      int		argcount;	/* number of "argvars" */
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 8023,8040 ****
Karsten Hopp ffaccd
      int		i;
Karsten Hopp ffaccd
      int		llen;
Karsten Hopp ffaccd
      ufunc_T	*fp;
Karsten Hopp ffaccd
-     int		cc;
Karsten Hopp ffaccd
  #define FLEN_FIXED 40
Karsten Hopp ffaccd
      char_u	fname_buf[FLEN_FIXED + 1];
Karsten Hopp ffaccd
      char_u	*fname;
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
      /*
Karsten Hopp ffaccd
       * In a script change <SID>name() and s:name() to K_SNR 123_name().
Karsten Hopp ffaccd
       * Change <SNR>123_name() to K_SNR 123_name().
Karsten Hopp ffaccd
       * Use fname_buf[] when it fits, otherwise allocate memory (slow).
Karsten Hopp ffaccd
       */
Karsten Hopp ffaccd
-     cc = name[len];
Karsten Hopp ffaccd
-     name[len] = NUL;
Karsten Hopp ffaccd
      llen = eval_fname_script(name);
Karsten Hopp ffaccd
      if (llen > 0)
Karsten Hopp ffaccd
      {
Karsten Hopp ffaccd
--- 8023,8044 ----
Karsten Hopp ffaccd
      int		i;
Karsten Hopp ffaccd
      int		llen;
Karsten Hopp ffaccd
      ufunc_T	*fp;
Karsten Hopp ffaccd
  #define FLEN_FIXED 40
Karsten Hopp ffaccd
      char_u	fname_buf[FLEN_FIXED + 1];
Karsten Hopp ffaccd
      char_u	*fname;
Karsten Hopp ffaccd
+     char_u	*name;
Karsten Hopp ffaccd
+ 
Karsten Hopp ffaccd
+     /* Make a copy of the name, if it comes from a funcref variable it could
Karsten Hopp ffaccd
+      * be changed or deleted in the called function. */
Karsten Hopp ffaccd
+     name = vim_strnsave(func_name, len);
Karsten Hopp ffaccd
+     if (name == NULL)
Karsten Hopp ffaccd
+ 	return ret;
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
      /*
Karsten Hopp ffaccd
       * In a script change <SID>name() and s:name() to K_SNR 123_name().
Karsten Hopp ffaccd
       * Change <SNR>123_name() to K_SNR 123_name().
Karsten Hopp ffaccd
       * Use fname_buf[] when it fits, otherwise allocate memory (slow).
Karsten Hopp ffaccd
       */
Karsten Hopp ffaccd
      llen = eval_fname_script(name);
Karsten Hopp ffaccd
      if (llen > 0)
Karsten Hopp ffaccd
      {
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 8205,8213 ****
Karsten Hopp ffaccd
  	}
Karsten Hopp ffaccd
      }
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
-     name[len] = cc;
Karsten Hopp ffaccd
      if (fname != name && fname != fname_buf)
Karsten Hopp ffaccd
  	vim_free(fname);
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
      return ret;
Karsten Hopp ffaccd
  }
Karsten Hopp ffaccd
--- 8209,8217 ----
Karsten Hopp ffaccd
  	}
Karsten Hopp ffaccd
      }
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
      if (fname != name && fname != fname_buf)
Karsten Hopp ffaccd
  	vim_free(fname);
Karsten Hopp ffaccd
+     vim_free(name);
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
      return ret;
Karsten Hopp ffaccd
  }
Karsten Hopp ffaccd
*** ../vim-7.2.439/src/testdir/test34.in	2007-09-25 17:59:15.000000000 +0200
Karsten Hopp ffaccd
--- src/testdir/test34.in	2010-05-28 21:54:36.000000000 +0200
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 35,40 ****
Karsten Hopp ffaccd
--- 35,45 ----
Karsten Hopp ffaccd
  :  let g:counter = 0
Karsten Hopp ffaccd
  :  return ''
Karsten Hopp ffaccd
  :endfunc
Karsten Hopp ffaccd
+ :func FuncWithRef(a)
Karsten Hopp ffaccd
+ :  unlet g:FuncRef
Karsten Hopp ffaccd
+ :  return a:a
Karsten Hopp ffaccd
+ :endfunc
Karsten Hopp ffaccd
+ :let g:FuncRef=function("FuncWithRef")
Karsten Hopp ffaccd
  :let counter = 0
Karsten Hopp ffaccd
  :inoremap <expr> ( ListItem()
Karsten Hopp ffaccd
  :inoremap <expr> [ ListReset()
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 47,52 ****
Karsten Hopp ffaccd
--- 52,58 ----
Karsten Hopp ffaccd
   ?=retval
Karsten Hopp ffaccd
   ?=Compute(45, 5, "retval")
Karsten Hopp ffaccd
   ?=retval
Karsten Hopp ffaccd
+  ?=g:FuncRef(333)
Karsten Hopp ffaccd
  
Karsten Hopp ffaccd
  XX+-XX
Karsten Hopp ffaccd
  ---*---
Karsten Hopp ffaccd
*** ../vim-7.2.439/src/testdir/test34.ok	2006-04-30 20:49:40.000000000 +0200
Karsten Hopp ffaccd
--- src/testdir/test34.ok	2010-05-28 21:56:03.000000000 +0200
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 1,4 ****
Karsten Hopp ffaccd
! xxx4asdf fail nop ok 9
Karsten Hopp ffaccd
  XX111XX
Karsten Hopp ffaccd
  ---222---
Karsten Hopp ffaccd
  1. one
Karsten Hopp ffaccd
--- 1,4 ----
Karsten Hopp ffaccd
! xxx4asdf fail nop ok 9 333
Karsten Hopp ffaccd
  XX111XX
Karsten Hopp ffaccd
  ---222---
Karsten Hopp ffaccd
  1. one
Karsten Hopp ffaccd
*** ../vim-7.2.439/src/version.c	2010-05-28 21:31:51.000000000 +0200
Karsten Hopp ffaccd
--- src/version.c	2010-05-28 22:03:30.000000000 +0200
Karsten Hopp ffaccd
***************
Karsten Hopp ffaccd
*** 683,684 ****
Karsten Hopp ffaccd
--- 683,686 ----
Karsten Hopp ffaccd
  {   /* Add new patch number below this line */
Karsten Hopp ffaccd
+ /**/
Karsten Hopp ffaccd
+     440,
Karsten Hopp ffaccd
  /**/
Karsten Hopp ffaccd
Karsten Hopp ffaccd
-- 
Karsten Hopp ffaccd
Nobody will ever need more than 640 kB RAM.
Karsten Hopp ffaccd
		-- Bill Gates, 1983
Karsten Hopp ffaccd
Windows 98 requires 16 MB RAM.
Karsten Hopp ffaccd
		-- Bill Gates, 1999
Karsten Hopp ffaccd
Logical conclusion: Nobody will ever need Windows 98.
Karsten Hopp ffaccd
Karsten Hopp ffaccd
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp ffaccd
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp ffaccd
\\\        download, build and distribute -- http://www.A-A-P.org        ///
Karsten Hopp ffaccd
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///