core dump / Objects/dictobject.c:471: bad argument to internal function

David Leonard david.leonard at csee.uq.edu.au
Sun Jun 17 06:48:02 CEST 2001


On Sat, 16 Jun 2001, (::) Bob Ippolito typed thusly:
> I got it to work.. what I had to do was turn off CIDict.. like this in setup.py
>
> > ActivePython 2.1, build 210
> > SystemError: Objects/dictobject.c:471: bad argument to internal
> > function
> > Segmentation fault (core dumped)

my lazily written CIDict module worked by copying the python dict type
and then 'patching' it so that it lowercased its keys. Python (2.0?)
seems to check that the objects being passed back are really dicts, and
so thats why you get an internal error.. which leads later to a core dump.

i've rewritten cidict to get rid of that ugly hack... the patch below
indicates what i've done .. i haven't committed (or compiled) it yet
because i am re-installing python2.1 on this machine at the moment.
i just wanted to let you know that i'll try and get it tested and fixed
today because its so awful.

and if anyone wants to run their eye over it for memory leaks, please do :)

d

Index: functions.c
===================================================================
RCS file: /cvsroot/python-ldap/python-ldap/Modules/functions.c,v
retrieving revision 1.4
diff -u -r1.4 functions.c
--- functions.c	2000/08/17 23:50:28	1.4
+++ functions.c	2001/06/17 04:39:31
@@ -10,6 +10,7 @@
 #include "LDAPObject.h"
 #include "errors.h"
 #include "template.h"
+#include "CIDict.h"

 /* ldap_open */

@@ -131,6 +132,16 @@
 "\tThis function returns true if url `looks like' an LDAP URL\n"
 "\t(as opposed to some other kind of URL).";

+#if defined(USE_CIDICT)
+static PyObject *
+cidict(PyObject *unused, PyObject *args)
+{
+	if (!PyArg_NoArgs(args))
+		return NULL;
+	return CIDict_New();
+}
+#endif
+
 /* methods */

 static PyMethodDef methods[] = {
@@ -146,6 +157,11 @@
     { "init_templates", (PyCFunction)l_init_templates,		METH_VARARGS,
     	l_init_templates_doc },
 #endif
+#if defined(USE_CIDICT)
+    { "cidict",		(PyCFunction)cidict,			METH_VARARGS,
+    	NULL },
+#endif
+
     { NULL, NULL }
 };

Index: CIDict.c
===================================================================
RCS file: /cvsroot/python-ldap/python-ldap/Modules/CIDict.c,v
retrieving revision 1.4
diff -u -r1.4 CIDict.c
--- CIDict.c	2001/05/12 08:08:39	1.4
+++ CIDict.c	2001/06/17 04:39:33
@@ -23,13 +23,18 @@
  * XXX I forget whose idea this originally was, but its a good one. - d
  */

+typedef struct {
+	PyObject_HEAD
+	PyObject *dict;
+} CIDictObject;
+
 /*
  * Return a new object representing a lowercased version of the argument.
  * Typically this is a string -> string conversion.
  * Returns: New Reference
  */
 static PyObject *
-case_insensitive(PyObject *o)
+lowercase(PyObject *o)
 {
 	char *str, *cp;
 	int len, i;
@@ -55,74 +60,146 @@
 	return s;
 }

-/* read-access the dictionary after lowercasing the subscript */
-
 static PyObject *
-cid_subscript(PyObject *d, PyObject *k)
+subscript(CIDictObject *self, PyObject *k)
 {
 	PyObject *ret;
 	PyObject *cik;

-	cik = case_insensitive(k);
-	ret = (*PyDict_Type.tp_as_mapping->mp_subscript)(d, cik);
-	Py_XDECREF(cik);
+	cik = lowercase(k);
+	if (cik == NULL)
+		return NULL;
+	ret = PyObject_GetItem(self->dict, cik);
+	Py_DECREF(cik);
 	return ret;
 }
+
+static int
+length(CIDictObject *self)
+{
+	return PyMapping_Length(self->dict);
+}

-/* write-access the dictionary after lowecasing the subscript */

 static int
-cid_ass_subscript(PyObject *d, PyObject *k, PyObject *v)
+ass_subscript(CIDictObject *self, PyObject *k, PyObject *v)
 {
 	int ret;
 	PyObject *cik;

-	cik = case_insensitive(k);
-	ret = (*PyDict_Type.tp_as_mapping->mp_ass_subscript)(d, cik, v);
-	Py_XDECREF(cik);
+	cik = lowercase(k);
+	if (cik == NULL)
+		return -1;
+	ret = PyObject_SetItem(self->dict, cik, v);
+	Py_DECREF(cik);
 	return ret;
 }

-/* This type and mapping structure gets filled in from the PyDict structs */
-
-static PyMappingMethods CIDict_mapping;
-PyTypeObject CIDict_Type;
+static void
+dealloc(CIDictObject *self)
+{
+	Py_DECREF(self->dict);
+	PyMem_DEL(self);
+}

-/* Initialise the case-insensitive dictionary type */
+static int
+print(CIDictObject *self, FILE *fp, int flags)
+{
+	return PyObject_Print(self->dict, fp, flags);
+}

-static void
-CIDict_init()
+PyObject *
+getattr(CIDictObject *self, char *attr_name)
+{
+	return PyObject_GetAttr(self->dict, attr_name);
+}
+
+static int
+compare(CIDictObject *self, PyObject *o)
+{
+	PyObject *lo = NULL;
+	PyObject *oitems = NULL;
+	PyObject *key = NULL;
+	PyObject *item = NULL;
+	int len, i, ret = -1;
+
+	if (!PyMapping_Check(o))
+		return PyObject_Compare(self->dict, o);
+
+	/* Create equivalent dictionary with lowercased keys */
+	if ((lo = PyDict_New()) == NULL)
+		goto done;
+	if ((oitems = PyMapping_Items(o)) == NULL)
+		goto done;
+	len = PyObject_Length(oitems);
+	for (i = 0; i < len; i++) {
+		Py_XDECREF(item);
+		if ((item = PySequence_GetItem(oitems, i)) == NULL)
+			goto done;
+		Py_XDECREF(key);
+		if ((key = lowercase(PyTuple_GET_ITEM(item, 0))) == NULL)
+			goto done;
+		PyMapping_SetItem(key, PyTuple_GET_ITEM(item, 1));
+	}
+	ret = PyObject_Compare(self->dict, lo);
+    done:
+	Py_XDECREF(key);
+	Py_XDECREF(item);
+	Py_XDECREF(oitems);
+	Py_XDECREF(lo);
+	return ret;
+}
+
+static PyObject *
+repr(CIDictObject *self)
 {
-	/*
-	 * Duplicate the standard python dictionary type,
-	 * but override the subscript accessor methods
-	 */
-	memcpy(&CIDict_Type, &PyDict_Type, sizeof CIDict_Type);
-	CIDict_Type.tp_name = "cidictionary";
-	CIDict_Type.tp_as_mapping = &CIDict_mapping;
-
-	memcpy(&CIDict_mapping, PyDict_Type.tp_as_mapping,
-		sizeof CIDict_mapping);
-	CIDict_mapping.mp_subscript = cid_subscript;
-	CIDict_mapping.mp_ass_subscript = cid_ass_subscript;
+	return PyObject_Repr(self->dict);
 }

+static PyMappingMethods as_mapping = {
+	length, 			/* mp_length */
+	subscript, 			/* mp_subscript */
+	ass_subscript			/* mp_ass_subscript */
+};
+
+PyTypeObject CIDict_Type = {
+#if defined(WIN32) || defined(__CYGWIN__)
+	/* see http://www.python.org/doc/FAQ.html#3.24 */
+	PyObject_HEAD_INIT(NULL)
+#else /* ! WIN32 */
+	PyObject_HEAD_INIT(&PyType_Type)
+#endif /* ! WIN32 */
+	"cidictionary",			/* tp_name */
+	sizeof (CIDictObject),		/* tp_basicsize */
+	0,				/* tp_itemsize */
+	(destructor)dealloc,		/* tp_dealloc */
+	(printfunc)print,		/* tp_print */
+	(getattrfunc)getattr,		/* tp_getattr */
+	NULL,				/* tp_setattr */
+	(cmpfunc)compare,		/* tp_compare */
+	(reprfunc)repr,			/* tp_repr */
+	NULL,				/* tp_as_number */
+	NULL,				/* tp_as_sequence */
+	&as_mapping,			/* tp_as_mapping */
+};
+
 /* Create a new case-insensitive dictionary, based on PyDict */

 PyObject *
 CIDict_New()
 {
-	PyObject *mp;
-	static int initialised = 0;
+	CIDictObject *o;
+	PyObject *dict;

-	if (!initialised) {
-		CIDict_init();
-		initialised = 1;
-	}
-
-	mp = PyDict_New();
-	mp->ob_type = &CIDict_Type;
-	return (mp);
+	dict = PyDict_New();
+	if (dict == NULL)
+		return NULL;
+	o = PyObject_NEW(CIDictObject, &CIDict_Type);
+	if (o == NULL)
+		Py_DECREF(dict);
+	else
+		o->dict = dict;
+	return o;
 }

 #endif /* USE_CIDICT */
-- 
David Leonard                           David.Leonard at dstc.edu.au
DSTC                                    Room:78-632  Ph:+61 7 336 58358
The University of Queensland            http://www.dstc.edu.au/
QLD 4072  AUSTRALIA                     B73CD65FBEF4C089B79A8EBADF1A932F13EA0FC8

.signature: Invalid argument





More information about the python-ldap mailing list