The current check for overlapping non-rebaseable DLLs uses a possible
outdated base address. It also could not detect multiple overlaps by one
non-rebaseable DLL.
Patch size may be misleading due to indentation change.
--
Regards,
Christian
From ee8a966cb6da48b45dfb6de3e732dade81ce7fb9 Mon Sep 17 00:00:00 2001
From: Christian Franke
Date: Sat, 16 Jul 2022 17:55:58 +0200
Subject: [PATCH] Ensure that no rebaseable DLL overlaps a non-rebaseable DLL
Restart rebase decision loop with newly sorted list if a DLL is not
rebaseable. Search for all DLLs which overlap such a DLL.
---
rebase.c | 203 +--
1 file changed, 121 insertions(+), 82 deletions(-)
diff --git a/rebase.c b/rebase.c
index 5cda123..39759a9 100644
--- a/rebase.c
+++ b/rebase.c
@@ -625,6 +625,7 @@ merge_image_info ()
{
int i, end;
img_info_t *match;
+ BOOL sorted;
ULONG64 floating_image_base;
/* Sort new files from command line by name. */
@@ -725,91 +726,129 @@ merge_image_info ()
img_info_rebase_start = 0;
}
- /* Now sort the old part of the list by base address. */
- if (img_info_rebase_start)
-qsort (img_info_list, img_info_rebase_start, sizeof (img_info_t),
- img_info_cmp);
- /* Perform several tests on the information fetched from the database
- to match with reality. */
- for (i = 0; i < img_info_rebase_start; ++i)
+ for (sorted = FALSE; img_info_rebase_start && !sorted; )
{
- ULONG64 cur_base, cur_base_orig;
- ULONG cur_size, slot_size;
-
- /* Files with the needs_rebasing or cannot_rebase flags set have been
-checked already. */
- if (img_info_list[i].flag.needs_rebasing
- || img_info_list[i].flag.cannot_rebase)
- continue;
- /* Check if the files in the old list still exist. Drop non-existant
-or unaccessible files. */
- if (access (img_info_list[i].name, F_OK) == -1
- || !GetImageInfos64 (img_info_list[i].name, NULL,
- &cur_base, &cur_size))
- {
- free (img_info_list[i].name);
- memmove (img_info_list + i, img_info_list + i + 1,
- (img_info_size - i - 1) * sizeof (img_info_t));
- --img_info_rebase_start;
- --img_info_size;
- continue;
- }
- slot_size = roundup2 (cur_size, ALLOCATION_SLOT);
- cur_base_orig = cur_base;
- /* If the file has been reinstalled, try to rebase to the same address
-in the first place. */
- if (cur_base != img_info_list[i].base)
+ char overlaps[img_info_rebase_start];
+ memset(overlaps, 0, img_info_rebase_start);
+ /* Now sort the old part of the list by base address. */
+ qsort (img_info_list, img_info_rebase_start, sizeof (img_info_t),
+img_info_cmp);
+ /* Perform several tests on the information fetched from the database
+to match with reality. */
+ for (sorted = TRUE, i = 0; sorted && i < img_info_rebase_start; ++i)
{
- img_info_list[i].flag.needs_rebasing = 1;
- if (verbose)
- fprintf (stderr, "rebasing %s because it's base has changed (due to
being reinstalled?)\n", img_info_list[i].name);
- /* Set cur_base to the old base to simplify subsequent tests. */
- cur_base = img_info_list[i].base;
- }
- /* However, if the DLL got bigger and doesn't fit into its slot
-anymore, rebase this DLL from scratch. */
- if (i + 1 < img_info_rebase_start
- && cur_base + slot_size + offset > img_info_list[i + 1].base)
- {
- img_info_list[i].base = 0;
- if (verbose)
- fprintf (stderr, "rebasing %s because it won't fit in it's old slot
without overlapping next DLL\n", img_info_list[i].name);
- }
- /* Does the previous DLL reach into the address space of this
-DLL? This happens if the previous DLL is not rebaseable. */
- else if (i > 0 && cur_base < img_info_list[i - 1].base
- + img_info_list[i - 1].slot_size)
- {
- img_info_list[i].base = 0;
- if (verbose)
- fprintf (stderr, "rebasing %s because previous DLL now overlaps\n",
img_info_list[i].name);
- }
- /* Does the file match the base address requirements? If not,
-rebase from scratch. */
- else if ((down_flag && cur_base + slot_size + offset > image_base)
- || (!down_flag && cur_base < image_base))
- {
- img_info_list[i].base = 0;
- if (verbose)
- fprintf (stderr, "rebasing %s because it's base address is outside
the expected area\n", img_info_list[i].name);
- }
- /* Make sure all DLLs with base address 0 have the needs_rebasing
-flag set. */
- if (img_info_list[i].base == 0)
- img_info_list[i].flag.needs_rebasing = 1;
- /* Only check for writability if file needs rebasing to keep
-Compact OS compression o