aboutsummaryrefslogtreecommitdiffstats
path: root/src/ralloc.c
diff options
context:
space:
mode:
authorEli Zaretskii2012-08-24 11:26:46 +0300
committerEli Zaretskii2012-08-24 11:26:46 +0300
commit36c46f8e09d5cb0cb8d2b19b9d3ad4826b5e163c (patch)
tree3ddb8fdb5d004cd2e150349816f4423dd796e826 /src/ralloc.c
parentdb148c21a9bc379f5147d5dfc4f53504308e60bc (diff)
downloademacs-36c46f8e09d5cb0cb8d2b19b9d3ad4826b5e163c.tar.gz
emacs-36c46f8e09d5cb0cb8d2b19b9d3ad4826b5e163c.zip
Fix bug #12242 with crashes in ralloc.c on OpenBSD.
src/ralloc.c (free_bloc): Don't dereference a 'heap' structure if it is not one of the heaps we manage.
Diffstat (limited to 'src/ralloc.c')
-rw-r--r--src/ralloc.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/src/ralloc.c b/src/ralloc.c
index b1a5982574f..fdcee7c7ef4 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -686,6 +686,7 @@ static void
686free_bloc (bloc_ptr bloc) 686free_bloc (bloc_ptr bloc)
687{ 687{
688 heap_ptr heap = bloc->heap; 688 heap_ptr heap = bloc->heap;
689 heap_ptr h;
689 690
690 if (r_alloc_freeze_level) 691 if (r_alloc_freeze_level)
691 { 692 {
@@ -715,20 +716,38 @@ free_bloc (bloc_ptr bloc)
715 bloc->prev->next = bloc->next; 716 bloc->prev->next = bloc->next;
716 } 717 }
717 718
718 /* Update the records of which blocs are in HEAP. */ 719 /* Sometimes, 'heap' obtained from bloc->heap above is not really a
719 if (heap->first_bloc == bloc) 720 'heap' structure. It can even be beyond the current break point,
721 which will cause crashes when we dereference it below (see
722 bug#12242). Evidently, the reason is bloc allocations done while
723 use_relocatable_buffers was non-positive, because additional
724 memory we get then is not recorded in the heaps we manage. If
725 bloc->heap records such a "heap", we cannot (and don't need to)
726 update its records. So we validate the 'heap' value by making
727 sure it is one of the heaps we manage via the heaps linked list,
728 and don't touch a 'heap' that isn't found there. This avoids
729 accessing memory we know nothing about. */
730 for (h = first_heap; h != NIL_HEAP; h = h->next)
731 if (heap == h)
732 break;
733
734 if (h)
720 { 735 {
721 if (bloc->next != 0 && bloc->next->heap == heap) 736 /* Update the records of which blocs are in HEAP. */
722 heap->first_bloc = bloc->next; 737 if (heap->first_bloc == bloc)
723 else 738 {
724 heap->first_bloc = heap->last_bloc = NIL_BLOC; 739 if (bloc->next != 0 && bloc->next->heap == heap)
725 } 740 heap->first_bloc = bloc->next;
726 if (heap->last_bloc == bloc) 741 else
727 { 742 heap->first_bloc = heap->last_bloc = NIL_BLOC;
728 if (bloc->prev != 0 && bloc->prev->heap == heap) 743 }
729 heap->last_bloc = bloc->prev; 744 if (heap->last_bloc == bloc)
730 else 745 {
731 heap->first_bloc = heap->last_bloc = NIL_BLOC; 746 if (bloc->prev != 0 && bloc->prev->heap == heap)
747 heap->last_bloc = bloc->prev;
748 else
749 heap->first_bloc = heap->last_bloc = NIL_BLOC;
750 }
732 } 751 }
733 752
734 relinquish (); 753 relinquish ();