Rev 3651: Handle references to line data in _patiencediff_c.c properly (Lalinský) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Wed Aug 27 05:41:43 BST 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3651
revision-id: pqm at pqm.ubuntu.com-20080827044137-4ox67ehr4bxtj7b0
parent: pqm at pqm.ubuntu.com-20080826151717-xb3qgwv6xta124k7
parent: aaron at aaronbentley.com-20080827040747-esn1l6aw5zt03sx6
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2008-08-27 05:41:37 +0100
message:
  Handle references to line data in _patiencediff_c.c properly (Lalinský)
modified:
  bzrlib/_patiencediff_c.c       _patiencediff_c.c-20070721205602-q3imkipwlgagp3cy-1
  bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3650.1.1
    revision-id: aaron at aaronbentley.com-20080827040747-esn1l6aw5zt03sx6
    parent: pqm at pqm.ubuntu.com-20080826151717-xb3qgwv6xta124k7
    parent: lalinsky at gmail.com-20080823130624-rvbasutb8urxkamy
    committer: Aaron Bentley <aaron at aaronbentley.com>
    branch nick: bzr.ab.integration
    timestamp: Wed 2008-08-27 00:07:47 -0400
    message:
      Merge patiencediff fix from Lukáš
    modified:
      bzrlib/_patiencediff_c.c       _patiencediff_c.c-20070721205602-q3imkipwlgagp3cy-1
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3628.1.3
    revision-id: lalinsky at gmail.com-20080823130624-rvbasutb8urxkamy
    parent: lalinsky at gmail.com-20080817193954-xtx7t19otspm7aac
    committer: Lukáš Lalinský <lalinsky at gmail.com>
    branch nick: patiencediff-refs
    timestamp: Sat 2008-08-23 15:06:24 +0200
    message:
      Add a test
    modified:
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3628.1.2
    revision-id: lalinsky at gmail.com-20080817193954-xtx7t19otspm7aac
    parent: lalinsky at gmail.com-20080817193103-nph9o92j2177iq96
    committer: Lukáš Lalinský <lalinsky at gmail.com>
    branch nick: patiencediff-refs
    timestamp: Sun 2008-08-17 21:39:54 +0200
    message:
      Actually free the data in delete_lines
    modified:
      bzrlib/_patiencediff_c.c       _patiencediff_c.c-20070721205602-q3imkipwlgagp3cy-1
    ------------------------------------------------------------
    revno: 3628.1.1
    revision-id: lalinsky at gmail.com-20080817193103-nph9o92j2177iq96
    parent: pqm at pqm.ubuntu.com-20080814042250-v7qws60l3fjwelb1
    committer: Lukáš Lalinský <lalinsky at gmail.com>
    branch nick: patiencediff-refs
    timestamp: Sun 2008-08-17 21:31:03 +0200
    message:
      Handle references to line data in _patiencediff_c.c properly
      
      This code is called in bzrlib only with lists or tuples of strings, which works fine, because PySequence_Fast always returns the same object and so the items from PySequence_Fast_GET_ITEM will not be deleted until the original sequence is deleted. But if it's called with a sequence than needs to be converted to list (e.g. PyUnicode), the items will be garbage collected in the contructor and still used later in code (which leads to segfaults).
    modified:
      bzrlib/_patiencediff_c.c       _patiencediff_c.c-20070721205602-q3imkipwlgagp3cy-1
=== modified file 'bzrlib/_patiencediff_c.c'
--- a/bzrlib/_patiencediff_c.c	2007-12-19 15:40:04 +0000
+++ b/bzrlib/_patiencediff_c.c	2008-08-17 19:39:54 +0000
@@ -541,6 +541,18 @@
 }
 
 
+static void
+delete_lines(struct line *lines, Py_ssize_t size)
+{
+    struct line *line = lines;
+    while (size-- > 0) {
+        Py_XDECREF(line->data);
+        line++;
+    }
+    free(lines);
+}
+
+
 static Py_ssize_t
 load_lines(PyObject *orig, struct line **lines)
 {
@@ -559,7 +571,8 @@
         return 0;
     }
 
-    line = *lines = (struct line *)malloc(sizeof(struct line) * size);
+    /* Allocate a memory block for line data, initialized to 0 */
+    line = *lines = (struct line *)calloc(size, sizeof(struct line));
     if (line == NULL) {
         PyErr_NoMemory();
         Py_DECREF(seq);
@@ -568,6 +581,7 @@
 
     for (i = 0; i < size; i++) {
         item = PySequence_Fast_GET_ITEM(seq, i);
+        Py_INCREF(item);
         line->data = item;
         line->hash = PyObject_Hash(item);
         if (line->hash == (-1)) {
@@ -581,6 +595,11 @@
 
     cleanup:
     Py_DECREF(seq);
+    if (size == -1) {
+        /* Error -- cleanup unused object references */
+        delete_lines(*lines, i);
+        *lines = NULL;
+    }
     return size;
 }
 
@@ -633,16 +652,16 @@
     free(backpointers);
     free(matches);
     free(hashtable.table);
-    free(b);
-    free(a);
+    delete_lines(b, bsize);
+    delete_lines(a, asize);
     return res;
 
 error:
     free(backpointers);
     free(matches);
     free(hashtable.table);
-    free(b);
-    free(a);
+    delete_lines(b, bsize);
+    delete_lines(a, asize);
     return NULL;
 }
 
@@ -711,16 +730,16 @@
     free(backpointers);
     free(matches.matches);
     free(hashtable.table);
-    free(b);
-    free(a);
+    delete_lines(b, bsize);
+    delete_lines(a, asize);
     Py_RETURN_NONE;
 
 error:
     free(backpointers);
     free(matches.matches);
     free(hashtable.table);
-    free(b);
-    free(a);
+    delete_lines(b, bsize);
+    delete_lines(a, asize);
     return NULL;
 }
 
@@ -769,8 +788,8 @@
 {
     free(self->backpointers);
     free(self->hashtable.table);
-    free(self->b);
-    free(self->a);
+    delete_lines(self->b, self->bsize);
+    delete_lines(self->a, self->asize);
     self->ob_type->tp_free((PyObject *)self);
 }
 

=== modified file 'bzrlib/tests/test_diff.py'
--- a/bzrlib/tests/test_diff.py	2008-07-08 14:55:19 +0000
+++ b/bzrlib/tests/test_diff.py	2008-08-23 13:06:24 +0000
@@ -769,6 +769,13 @@
         self._PatienceSequenceMatcher = \
             bzrlib._patiencediff_py.PatienceSequenceMatcher_py
 
+    def test_diff_unicode_string(self):
+        a = ''.join([unichr(i) for i in range(4000, 4500, 3)])
+        b = ''.join([unichr(i) for i in range(4300, 4800, 2)])
+        sm = self._PatienceSequenceMatcher(None, a, b)
+        mb = sm.get_matching_blocks()
+        self.assertEquals(35, len(mb))
+
     def test_unique_lcs(self):
         unique_lcs = self._unique_lcs
         self.assertEquals(unique_lcs('', ''), [])




More information about the bazaar-commits mailing list