Blob Blame History Raw
To: vim_dev@googlegroups.com
Subject: Patch 7.3.1077
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.3.1077
Problem:    Python: Allocating dict the wrong way, causing a crash.
Solution:   Use py_dict_alloc(). Fix some exception problems. (ZyX)
Files:	    src/if_py_both.h


*** ../vim-7.3.1076/src/if_py_both.h	2013-05-30 19:01:20.000000000 +0200
--- src/if_py_both.h	2013-05-30 21:53:00.000000000 +0200
***************
*** 26,56 ****
  
  #define PyErr_SetVim(str) PyErr_SetString(VimError, str)
  
  #define INVALID_BUFFER_VALUE ((buf_T *)(-1))
  #define INVALID_WINDOW_VALUE ((win_T *)(-1))
  #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
  
- #define DICTKEY_DECL \
-     PyObject	*dictkey_todecref = NULL;
- #define DICTKEY_GET(err, decref) \
-     if (!(key = StringToChars(keyObject, &dictkey_todecref))) \
-     { \
- 	if (decref) \
- 	{ \
- 	    Py_DECREF(keyObject); \
- 	} \
- 	return err; \
-     } \
-     if (decref && !dictkey_todecref) \
- 	dictkey_todecref = keyObject; \
-     if (*key == NUL) \
-     { \
- 	PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
- 	return err; \
-     }
- #define DICTKEY_UNREF \
-     Py_XDECREF(dictkey_todecref);
- 
  typedef void (*rangeinitializer)(void *);
  typedef void (*runner)(const char *, void *
  #ifdef PY_CAN_RECURSE
--- 26,38 ----
  
  #define PyErr_SetVim(str) PyErr_SetString(VimError, str)
  
+ #define RAISE_NO_EMPTY_KEYS PyErr_SetString(PyExc_ValueError, \
+ 						_("empty keys are not allowed"))
+ 
  #define INVALID_BUFFER_VALUE ((buf_T *)(-1))
  #define INVALID_WINDOW_VALUE ((win_T *)(-1))
  #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
  
  typedef void (*rangeinitializer)(void *);
  typedef void (*runner)(const char *, void *
  #ifdef PY_CAN_RECURSE
***************
*** 1016,1023 ****
      dictitem_T	*di;
      dict_T	*dict = self->dict;
      hashitem_T	*hi;
! 
!     DICTKEY_DECL
  
      if (flags & DICT_FLAG_HAS_DEFAULT)
      {
--- 998,1004 ----
      dictitem_T	*di;
      dict_T	*dict = self->dict;
      hashitem_T	*hi;
!     PyObject	*todecref;
  
      if (flags & DICT_FLAG_HAS_DEFAULT)
      {
***************
*** 1030,1040 ****
      if (flags & DICT_FLAG_RETURN_BOOL)
  	defObject = Py_False;
  
!     DICTKEY_GET(NULL, 0)
  
      hi = hash_find(&dict->dv_hashtab, key);
  
!     DICTKEY_UNREF
  
      if (HASHITEM_EMPTY(hi))
      {
--- 1011,1028 ----
      if (flags & DICT_FLAG_RETURN_BOOL)
  	defObject = Py_False;
  
!     if (!(key = StringToChars(keyObject, &todecref)))
! 	return NULL;
! 
!     if (*key == NUL)
!     {
! 	RAISE_NO_EMPTY_KEYS;
! 	return NULL;
!     }
  
      hi = hash_find(&dict->dv_hashtab, key);
  
!     Py_XDECREF(todecref);
  
      if (HASHITEM_EMPTY(hi))
      {
***************
*** 1173,1179 ****
      typval_T	tv;
      dict_T	*dict = self->dict;
      dictitem_T	*di;
!     DICTKEY_DECL
  
      if (dict->dv_lock)
      {
--- 1161,1167 ----
      typval_T	tv;
      dict_T	*dict = self->dict;
      dictitem_T	*di;
!     PyObject	*todecref;
  
      if (dict->dv_lock)
      {
***************
*** 1181,1187 ****
  	return -1;
      }
  
!     DICTKEY_GET(-1, 0)
  
      di = dict_find(dict, key, -1);
  
--- 1169,1181 ----
  	return -1;
      }
  
!     if (!(key = StringToChars(keyObject, &todecref)))
! 	return -1;
!     if (*key == NUL)
!     {
! 	RAISE_NO_EMPTY_KEYS;
! 	return -1;
!     }
  
      di = dict_find(dict, key, -1);
  
***************
*** 1191,1197 ****
  
  	if (di == NULL)
  	{
! 	    DICTKEY_UNREF
  	    PyErr_SetObject(PyExc_KeyError, keyObject);
  	    return -1;
  	}
--- 1185,1191 ----
  
  	if (di == NULL)
  	{
! 	    Py_XDECREF(todecref);
  	    PyErr_SetObject(PyExc_KeyError, keyObject);
  	    return -1;
  	}
***************
*** 1208,1213 ****
--- 1202,1208 ----
      {
  	if (!(di = dictitem_alloc(key)))
  	{
+ 	    Py_XDECREF(todecref);
  	    PyErr_NoMemory();
  	    return -1;
  	}
***************
*** 1216,1222 ****
  
  	if (dict_add(dict, di) == FAIL)
  	{
! 	    DICTKEY_UNREF
  	    vim_free(di);
  	    dictitem_free(di);
  	    PyErr_SetVim(_("failed to add key to dictionary"));
--- 1211,1217 ----
  
  	if (dict_add(dict, di) == FAIL)
  	{
! 	    Py_XDECREF(todecref);
  	    vim_free(di);
  	    dictitem_free(di);
  	    PyErr_SetVim(_("failed to add key to dictionary"));
***************
*** 1226,1232 ****
      else
  	clear_tv(&di->di_tv);
  
!     DICTKEY_UNREF
  
      copy_tv(&tv, &di->di_tv);
      clear_tv(&tv);
--- 1221,1227 ----
      else
  	clear_tv(&di->di_tv);
  
!     Py_XDECREF(todecref);
  
      copy_tv(&tv, &di->di_tv);
      clear_tv(&tv);
***************
*** 2202,2218 ****
      int		flags;
      long	numval;
      char_u	*stringval;
!     DICTKEY_DECL
  
      if (self->Check(self->from))
  	return NULL;
  
!     DICTKEY_GET(NULL, 0)
  
      flags = get_option_value_strict(key, &numval, &stringval,
  				    self->opt_type, self->from);
  
!     DICTKEY_UNREF
  
      if (flags == 0)
      {
--- 2197,2219 ----
      int		flags;
      long	numval;
      char_u	*stringval;
!     PyObject	*todecref;
  
      if (self->Check(self->from))
  	return NULL;
  
!     if (!(key = StringToChars(keyObject, &todecref)))
! 	return NULL;
!     if (*key == NUL)
!     {
! 	RAISE_NO_EMPTY_KEYS;
! 	return NULL;
!     }
  
      flags = get_option_value_strict(key, &numval, &stringval,
  				    self->opt_type, self->from);
  
!     Py_XDECREF(todecref);
  
      if (flags == 0)
      {
***************
*** 2329,2340 ****
      int		flags;
      int		opt_flags;
      int		r = 0;
!     DICTKEY_DECL
  
      if (self->Check(self->from))
  	return -1;
  
!     DICTKEY_GET(-1, 0)
  
      flags = get_option_value_strict(key, NULL, NULL,
  				    self->opt_type, self->from);
--- 2330,2347 ----
      int		flags;
      int		opt_flags;
      int		r = 0;
!     PyObject	*todecref;
  
      if (self->Check(self->from))
  	return -1;
  
!     if (!(key = StringToChars(keyObject, &todecref)))
! 	return -1;
!     if (*key == NUL)
!     {
! 	RAISE_NO_EMPTY_KEYS;
! 	return -1;
!     }
  
      flags = get_option_value_strict(key, NULL, NULL,
  				    self->opt_type, self->from);
***************
*** 2342,2348 ****
      if (flags == 0)
      {
  	PyErr_SetObject(PyExc_KeyError, keyObject);
! 	DICTKEY_UNREF
  	return -1;
      }
  
--- 2349,2355 ----
      if (flags == 0)
      {
  	PyErr_SetObject(PyExc_KeyError, keyObject);
! 	Py_XDECREF(todecref);
  	return -1;
      }
  
***************
*** 2352,2371 ****
  	{
  	    PyErr_SetString(PyExc_ValueError,
  		    _("unable to unset global option"));
! 	    DICTKEY_UNREF
  	    return -1;
  	}
  	else if (!(flags & SOPT_GLOBAL))
  	{
  	    PyErr_SetString(PyExc_ValueError, _("unable to unset option "
  						"without global value"));
! 	    DICTKEY_UNREF
  	    return -1;
  	}
  	else
  	{
  	    unset_global_local_option(key, self->from);
! 	    DICTKEY_UNREF
  	    return 0;
  	}
      }
--- 2359,2378 ----
  	{
  	    PyErr_SetString(PyExc_ValueError,
  		    _("unable to unset global option"));
! 	    Py_XDECREF(todecref);
  	    return -1;
  	}
  	else if (!(flags & SOPT_GLOBAL))
  	{
  	    PyErr_SetString(PyExc_ValueError, _("unable to unset option "
  						"without global value"));
! 	    Py_XDECREF(todecref);
  	    return -1;
  	}
  	else
  	{
  	    unset_global_local_option(key, self->from);
! 	    Py_XDECREF(todecref);
  	    return 0;
  	}
      }
***************
*** 2396,2402 ****
  	else
  	{
  	    PyErr_SetString(PyExc_TypeError, _("object must be integer"));
! 	    DICTKEY_UNREF
  	    return -1;
  	}
  
--- 2403,2409 ----
  	else
  	{
  	    PyErr_SetString(PyExc_TypeError, _("object must be integer"));
! 	    Py_XDECREF(todecref);
  	    return -1;
  	}
  
***************
*** 2418,2424 ****
  	    r = -1;
      }
  
!     DICTKEY_UNREF
  
      return r;
  }
--- 2425,2431 ----
  	    r = -1;
      }
  
!     Py_XDECREF(todecref);
  
      return r;
  }
***************
*** 4528,4534 ****
      PyObject	*valObject;
      Py_ssize_t	iter = 0;
  
!     if (!(dict = dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
--- 4535,4541 ----
      PyObject	*valObject;
      Py_ssize_t	iter = 0;
  
!     if (!(dict = py_dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
***************
*** 4553,4558 ****
--- 4560,4566 ----
  	{
  	    dict_unref(dict);
  	    Py_XDECREF(todecref);
+ 	    RAISE_NO_EMPTY_KEYS;
  	    return -1;
  	}
  
***************
*** 4600,4606 ****
      PyObject	*keyObject;
      PyObject	*valObject;
  
!     if (!(dict = dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
--- 4608,4614 ----
      PyObject	*keyObject;
      PyObject	*valObject;
  
!     if (!(dict = py_dict_alloc()))
  	return -1;
  
      tv->v_type = VAR_DICT;
***************
*** 4637,4642 ****
--- 4645,4651 ----
  	    Py_DECREF(iterator);
  	    Py_XDECREF(todecref);
  	    dict_unref(dict);
+ 	    RAISE_NO_EMPTY_KEYS;
  	    return -1;
  	}
  
*** ../vim-7.3.1076/src/version.c	2013-05-30 21:42:09.000000000 +0200
--- src/version.c	2013-05-30 21:49:50.000000000 +0200
***************
*** 730,731 ****
--- 730,733 ----
  {   /* Add new patch number below this line */
+ /**/
+     1077,
  /**/

-- 
The History of every major Galactic Civilization tends to pass through
three distinct and recognizable phases, those of Survival, Inquiry and
Sophistication, otherwise known as the How, Why and Where phases.
For instance, the first phase is characterized by the question 'How can
we eat?' the second by the question 'Why do we eat?' and the third by
the question 'Where shall we have lunch?'
		-- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"

 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///