diff options
| author | Eli Zaretskii | 2012-08-24 11:26:46 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2012-08-24 11:26:46 +0300 |
| commit | 36c46f8e09d5cb0cb8d2b19b9d3ad4826b5e163c (patch) | |
| tree | 3ddb8fdb5d004cd2e150349816f4423dd796e826 /src/ralloc.c | |
| parent | db148c21a9bc379f5147d5dfc4f53504308e60bc (diff) | |
| download | emacs-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.c | 45 |
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 | |||
| 686 | free_bloc (bloc_ptr bloc) | 686 | free_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 (); |