~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_patiencediff_c.c

  • Committer: Lukáš Lalinský
  • Date: 2008-08-17 19:31:03 UTC
  • mto: (3650.1.1 bzr.ab.integration)
  • mto: This revision was merged to the branch mainline in revision 3651.
  • Revision ID: lalinsky@gmail.com-20080817193103-nph9o92j2177iq96
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).

Show diffs side-by-side

added added

removed removed

Lines of Context:
541
541
}
542
542
 
543
543
 
 
544
static void
 
545
delete_lines(struct line *lines, Py_ssize_t size)
 
546
{
 
547
    while (size-- > 0) {
 
548
        Py_XDECREF(lines->data);
 
549
        lines++;
 
550
    }
 
551
}
 
552
 
 
553
 
544
554
static Py_ssize_t
545
555
load_lines(PyObject *orig, struct line **lines)
546
556
{
559
569
        return 0;
560
570
    }
561
571
 
562
 
    line = *lines = (struct line *)malloc(sizeof(struct line) * size);
 
572
    /* Allocate a memory block for line data, initialized to 0 */
 
573
    line = *lines = (struct line *)calloc(size, sizeof(struct line));
563
574
    if (line == NULL) {
564
575
        PyErr_NoMemory();
565
576
        Py_DECREF(seq);
568
579
 
569
580
    for (i = 0; i < size; i++) {
570
581
        item = PySequence_Fast_GET_ITEM(seq, i);
 
582
        Py_INCREF(item);
571
583
        line->data = item;
572
584
        line->hash = PyObject_Hash(item);
573
585
        if (line->hash == (-1)) {
581
593
 
582
594
    cleanup:
583
595
    Py_DECREF(seq);
 
596
    if (size == -1) {
 
597
        /* Error -- cleanup unused object references */
 
598
        delete_lines(*lines, i);
 
599
    }
584
600
    return size;
585
601
}
586
602
 
633
649
    free(backpointers);
634
650
    free(matches);
635
651
    free(hashtable.table);
636
 
    free(b);
637
 
    free(a);
 
652
    delete_lines(b, bsize);
 
653
    delete_lines(a, asize);
638
654
    return res;
639
655
 
640
656
error:
641
657
    free(backpointers);
642
658
    free(matches);
643
659
    free(hashtable.table);
644
 
    free(b);
645
 
    free(a);
 
660
    delete_lines(b, bsize);
 
661
    delete_lines(a, asize);
646
662
    return NULL;
647
663
}
648
664
 
711
727
    free(backpointers);
712
728
    free(matches.matches);
713
729
    free(hashtable.table);
714
 
    free(b);
715
 
    free(a);
 
730
    delete_lines(b, bsize);
 
731
    delete_lines(a, asize);
716
732
    Py_RETURN_NONE;
717
733
 
718
734
error:
719
735
    free(backpointers);
720
736
    free(matches.matches);
721
737
    free(hashtable.table);
722
 
    free(b);
723
 
    free(a);
 
738
    delete_lines(b, bsize);
 
739
    delete_lines(a, asize);
724
740
    return NULL;
725
741
}
726
742
 
769
785
{
770
786
    free(self->backpointers);
771
787
    free(self->hashtable.table);
772
 
    free(self->b);
773
 
    free(self->a);
 
788
    delete_lines(self->b, self->bsize);
 
789
    delete_lines(self->a, self->asize);
774
790
    self->ob_type->tp_free((PyObject *)self);
775
791
}
776
792