Re: Patch to fix crashes with python debug

"Edson Tadeu M. Manoel" <[email protected]> Thu, 11 Sep 2014 08:58:15 -0300
Newsgroups gmane.comp.python.egenix.user
Message-ID <CAPa1mMvaxn4pzsi60BH0o4Dp3=_vEB3306CK7Un8AFEeP38pgg@mail.gmail.com>
Please find the patch attached.

It applies to mx version 3.2.5. It fixes the problem where `_ob_next` and
`_ob_prev` were being rewritten by the `mxDateTime_FreeList` mechanism, and
also where `mxDateTime` objects were being deallocated without previously
"rewiring" the `_ob_next` and `_ob_prev` links (by calling `mxDateTime_Free`
directly, who called `PyObject_Del` directly instead of using `Py_DECREF`
or `Py_XDECREF` or `Py_Clear`).

I'm also attaching a very simple test case that is fixed by the patch (the
test crashed in python debug).

  Thanks,
    Edson Tadeu M. Manoel



On Wed, Sep 10, 2014 at 6:40 PM, Edson Tadeu M. Manoel <[email protected]>
wrote:

> Hi,
>
>   I have a patch proposal to fix problems in mx.DateTime that causes
> crashes in the debug version of Python (I'm testing on Python 2.7).
> Specifically, the problem happens when there is an error raised from one of
> the "constructors".  Where can I send it?  I didn't find any official
> repository or issue tracking system.  Is this list a good place?
>
>
>   Thanks.
>
>  <http://www.esss.com.br/>
>



-- 
*Edson Tadeu M. Manoel*


*Senior Scientific Developer*
ESSS - SIMULATING THE FUTURE | Florianópolis - SC - Brazil
Office: +55 (48) 3953 0033 | Skype: *tadeu.esss | www.esss.com.br
<http://www.esss.com.br/>*

*  <http://www.esss.com.br>*

<http://www.esss.com.br/>


_______________________________________________________________________
eGenix.com User Mailing List                     http://www.egenix.com/
https://www.egenix.com/mailman/listinfo/egenix-users
fix-crashes-in-debug-in-mx.DateTime-caused-by-errors.patch (application/octet-stream, 3.4 KB)
---
diff --git a/mx/DateTime/mxDateTime/mxDateTime.c b/mx/DateTime/mxDateTime/mxDateTime.c
--- a/mx/DateTime/mxDateTime/mxDateTime.c
+++ b/mx/DateTime/mxDateTime/mxDateTime.c
@@ -91,8 +91,10 @@
 #define STRFTIME_OUTPUT_SIZE	1024
 
 /* Define these to have the module use free lists (saves malloc calls) */
+#ifndef _DEBUG
 #define MXDATETIME_FREELIST
 #define MXDATETIMEDELTA_FREELIST
+#endif
 
 /* Define this to enable the copy-protocol (__copy__, __deepcopy__) */
 #define COPY_PROTOCOL
@@ -1415,7 +1417,8 @@ PyObject *mxDateTime_FromDateAndTime(long year,
 
     return (PyObject *)datetime;
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1443,7 +1446,8 @@ PyObject *mxDateTime_FromJulianDateAndTime(long year,
 
     return (PyObject *)datetime;
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1464,7 +1468,8 @@ PyObject *mxDateTime_FromAbsDateAndTime(long absdate,
 
     return (PyObject *)datetime;
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1487,7 +1492,8 @@ PyObject *mxDateTime_FromAbsDateTime(long absdate,
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1565,7 +1571,8 @@ PyObject *mxDateTime_FromDateTimeAndOffset(mxDateTimeObject *datetime,
     return (PyObject *)dt;
 
  onError:
-    mxDateTime_Free(dt);
+    assert(Py_REFCNT(dt) == 1);
+    Py_CLEAR(dt);
     return NULL;
 }
 
@@ -1595,7 +1602,8 @@ PyObject *mxDateTime_FromAbsDays(double absdays)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1628,7 +1636,8 @@ PyObject *mxDateTime_FromTuple(PyObject *v)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1654,7 +1663,8 @@ PyObject *mxDateTime_FromTmStruct(struct tm *tm)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1691,7 +1701,8 @@ PyObject *mxDateTime_FromTicks(double ticks)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1723,7 +1734,8 @@ PyObject *mxDateTime_FromGMTicks(double ticks)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -1741,7 +1753,8 @@ PyObject *mxDateTime_FromCOMDate(double comdate)
     return (PyObject *)datetime;
 
  onError:
-    mxDateTime_Free(datetime);
+    assert(Py_REFCNT(datetime) == 1);
+    Py_CLEAR(datetime);
     return NULL;
 }
 
@@ -3875,7 +3888,7 @@ PyTypeObject mxDateTime_Type = {
     mxDateTime_Initialize,		/* tp_init */
     mxDateTime_Allocate,		/* tp_alloc */
     PyType_GenericNew,			/* tp_new */
-    (destructor)mxDateTime_Free,	/* tp_free */
+    0,					/* tp_free */
     0,					/* tp_is_gc */
     0,					/* tp_bases */
     0,					/* tp_mro */
--
pytest_mx_datetime.py (application/octet-stream, 455 B)
import mx.DateTime
import pytest


MX_LAST_VALID_YEAR = 5867440  # MAX_LONG / 366


def testCreateMxDateTime():
    '''
    This causes a crash in Debug (before patch in mx).
    '''
    dt1 = mx.DateTime.DateTime(MX_LAST_VALID_YEAR, 12, 31)
    with pytest.raises(mx.DateTime.RangeError) as exc_info:
        dt2 = mx.DateTime.DateTime(MX_LAST_VALID_YEAR + 1, 1, 1)
    assert exc_info.value.message == 'year out of range: %d' % (MX_LAST_VALID_YEAR + 1)