[Python-bugs-list] apply(): throws MemoryError when sending an {} as the keyword list (PR#85)

sdunn@digitalanvil.com sdunn@digitalanvil.com
Thu, 23 Sep 1999 23:03:51 -0400 (EDT)


Full_Name: Sean Dunn
Version: 1.5.2
OS: Irix 6.5
Submission from: da111.digitalanvil.com (208.10.150.111)


Description: 
	The builtin function apply() seems to barf on empty dictionaries
	when passed as the keyword list.  See the following output:

###
Python 1.5.2 (#33, Sep 23 1999, 21:46:26) [C] on irix6
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> def func(a):
...     return a
... 
>>> print func
<function func at 1018aa68>
>>> func(1)
1
>>> apply(func, (1,))
1
>>> apply(func, (1,), {})
Traceback (innermost last):
  File "<stdin>", line 1, in ?
MemoryError
>>> 
###


I first found this problem when trying to simply import the 'threading' module:

###
Python 1.5.2 (#33, Sep 23 1999, 21:46:26) [C] on irix6
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import threading
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "./Lib/threading.py", line 545, in ?
    _MainThread()
  File "./Lib/threading.py", line 460, in __init__
    Thread.__init__(self, name="MainThread")
  File "./Lib/threading.py", line 332, in __init__
    self.__block = Condition(Lock())
  File "./Lib/threading.py", line 136, in Condition
    return apply(_Condition, args, kwargs)
MemoryError
>>> 
###


The variable 'kwargs' in this case is {}.  The actual exception is thrown
at line 2467 of Python/ceval.c:

	if (kw != NULL) {
		int pos, i;
		nk = PyDict_Size(kw);

/* 2467 */	k = PyMem_NEW(PyObject *, 2*nk);
/* nk, the PyDict_Size (the size of ma_used) is 0 */

		if (k == NULL) {
			PyErr_NoMemory();
			Py_DECREF(arg);
			return NULL;
		}
		pos = i = 0;
		while (PyDict_Next(kw, &pos, &k[i], &k[i+1]))
			i += 2;
		nk = i/2;
		/* XXX This is broken if the caller deletes dict items! */
	}



Currently, I am making the following change to threading to catch {} kwargs:

###
def Condition(*args, **kwargs):
    if kwargs=={}:
	return apply(_Condition, args)
    else:
	return apply(_Condition, args, kwargs)
###