Package: python-gtk2
Version: 2.6.3-2
Severity: normal
Tags: patch

There's a typo in codegen/argtypes.py that causes an incorrect type
mapping on 64 bit architectures; it looks like some new lines were
pasted in between the maps for guint and guint32, which made the value
of the local 'args' variable incorrect.

This is causing a bug that makes quodlibet unusable on 64 bit
architectures if the event time exceeds 2**31; it also could potentially
cause many other bugs.

Attached is a patch to use PyGTK 2.8's argtypes.py, which defines it
correctly.
-- 
Joe Wreschnig <[EMAIL PROTECTED]>
--- pygtk-2.6.3.orig/codegen/argtypes.py
+++ pygtk-2.6.3/codegen/argtypes.py
@@ -175,16 +175,36 @@
         info.codeafter.append('    return PyInt_FromLong(ret);')

 class UIntArg(ArgType):
+    dflt = ('    if (py_%(name)s) {\n'
+            '        if (PyLong_Check(py_%(name)s))\n'
+            '            %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
+            '        else if (PyInt_Check(py_%(name)s))\n'
+            '            %(name)s = PyInt_AsLong(py_%(name)s);\n'
+            '        else\n'
+            '            PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
+            '        if (PyErr_Occurred())\n'
+            '            return NULL;\n'
+            '    }\n')
+    before = ('    if (PyLong_Check(py_%(name)s))\n'
+              '        %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
+              '    else if (PyInt_Check(py_%(name)s))\n'
+              '        %(name)s = PyInt_AsLong(py_%(name)s);\n'
+              '    else\n'
+              '        PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
+              '    if (PyErr_Occurred())\n'
+              '        return NULL;\n')
     def write_param(self, ptype, pname, pdflt, pnull, info):
-       if pdflt:
-           info.varlist.add(ptype, pname + ' = ' + pdflt)
-       else:
-           info.varlist.add(ptype, pname)
-       info.arglist.append(pname)
-        info.add_parselist('I', ['&' + pname], [pname])
+        if not pdflt:
+            pdflt = '0';
+
+        info.varlist.add(ptype, pname + ' = ' + pdflt)
+        info.codebefore.append(self.dflt % {'name':pname})
+        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
+        info.arglist.append(pname)
+        info.add_parselist('O', ['&py_' + pname], [pname])
     def write_return(self, ptype, ownsreturn, info):
         info.varlist.add(ptype, 'ret')
-        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
+        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);')

 class SizeArg(ArgType):

@@ -264,22 +284,30 @@
         info.codeafter.append('    return PyInt_FromLong(ret);')

 class ULongArg(ArgType):
-    dflt = '    if (py_%(name)s)\n' \
-           '        %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
-    before = '    %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
     def write_param(self, ptype, pname, pdflt, pnull, info):
-        if pdflt:
-            info.varlist.add('gulong', pname + ' = ' + pdflt)
-            info.codebefore.append(self.dflt % {'name':pname})
-        else:
-            info.varlist.add('gulong', pname)
-            info.codebefore.append(self.before % {'name':pname})
-        info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
-        info.arglist.append(pname)
-        info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname])
+       if pdflt:
+           info.varlist.add('unsigned long', pname + ' = ' + pdflt)
+       else:
+           info.varlist.add('unsigned long', pname)
+       info.arglist.append(pname)
+        info.add_parselist('k', ['&' + pname], [pname])
     def write_return(self, ptype, ownsreturn, info):
-        info.varlist.add('gulong', 'ret')
-        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);')
+        info.varlist.add(ptype, 'ret')
+        info.codeafter.append('    return PyLong_FromUnsignedLong(ret);\n')
+
+class UInt32Arg(ULongArg):
+    def write_param(self, ptype, pname, pdflt, pnull, info):
+        ULongArg.write_param(self, ptype, pname, pdflt, pnull, info)
+        ## if sizeof(unsigned long) > sizeof(unsigned int), we need to
+        ## check the value is within guint32 range
+        if struct.calcsize('L') > struct.calcsize('I'):
+            info.codebefore.append((
+                '    if (%(pname)s > G_MAXUINT32) {\n'
+                '        PyErr_SetString(PyExc_ValueError,\n'
+                '                        "Value out of range in conversion of"\n'
+                '                        " %(pname)s parameter to unsigned 32 bit integer");\n'
+                '        return NULL;\n'
+                '    }\n') % vars())

 class Int64Arg(ArgType):
     def write_param(self, ptype, pname, pdflt, pnull, info):
@@ -901,13 +929,7 @@
 arg = TimeTArg()
 matcher.register('time_t', arg)

-# If the system maxint is smaller than unsigned int, we need to use
-# Long objects with PyLong_AsUnsignedLong
-if sys.maxint >= (1L << 32):
-    matcher.register('guint32', arg)
-else:
-    arg = ULongArg()
-    matcher.register('guint32', arg)
+matcher.register('guint32', UInt32Arg())

 arg = ULongArg()
 matcher.register('gulong', arg)

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to