From 1b184f57409d6957ae0940d2938f59350f1d1d32 Mon Sep 17 00:00:00 2001 From: York Jasper Niebuhr Date: Tue, 28 Oct 2025 00:34:13 +0100 Subject: [PATCH] Fixed selfpatch randomizer --- selfpatch/src/targets.c | 78 +++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/selfpatch/src/targets.c b/selfpatch/src/targets.c index b6126bb..54ac537 100644 --- a/selfpatch/src/targets.c +++ b/selfpatch/src/targets.c @@ -161,13 +161,6 @@ static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t const struct ShuffleRegion* origin, uint32_t alignment) { uint32_t count = 0; - /* - TODO - Self overlap... - 1. Can skip swap check for origin field - 2. Origin field can however reduce one side of the origin region if it still overlaps - */ - uint32_t current_field = 0; for (uint32_t offset = 0; offset < target->size; offset += alignment) { // Placing the origin region here or further would exceed struct boundaries @@ -180,10 +173,23 @@ static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t + target->fields[current_field].size <= offset) current_field++; // If origin->fill_begin was placed at offset, could all fields that overlap with range swap with origin? + uint32_t true_origin_region_begin = origin->begin; + uint32_t true_origin_region_end = origin->end; + + if (offset <= origin->fill_begin && option_would_end > true_origin_region_begin) + true_origin_region_begin = option_would_end; + + if (offset >= origin->fill_begin && offset < true_origin_region_end) + true_origin_region_end = offset; + int conflict = 0; - uint32_t origin_region_ptr = origin->begin; + uint32_t origin_region_ptr = true_origin_region_begin; for (uint32_t it = current_field; it < target->field_count; it++) { struct Field* f = &target->fields[it]; + + if (f->offset == origin->fill_begin) + continue; + if (f->offset >= option_would_end) break; @@ -198,7 +204,7 @@ static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t origin_region_ptr += f->size; - if (origin_region_ptr > origin->end) { + if (origin_region_ptr > true_origin_region_end) { conflict = 1; break; } @@ -211,21 +217,25 @@ static uint32_t target_get_shuffle_options(const struct Target* target, uint32_t return count; } -static void print_indices(const char* txt, const struct Target* target) { - // TODO - printf("%s\n", txt); - for (uint32_t i = 0; i < target->field_count; i++) { - printf(" %u\n", target->fields[i].initial_idx); - } -} - static void target_swap(struct Target* target, uint32_t origin_idx, const struct ShuffleRegion* origin_region, uint32_t new_offset) { - print_indices("Before swap:", target); - int origin_pulled = 0; - uint32_t origin_region_ptr = origin_region->begin; + int pulled = 0; + uint32_t option_fill_end = new_offset + (origin_region->fill_end - origin_region->fill_begin); + + // If origin->fill_begin was placed at offset, could all fields that overlap with range swap with origin? + uint32_t true_origin_region_begin = origin_region->begin; + + if (new_offset <= origin_region->fill_begin && option_fill_end > true_origin_region_begin) + true_origin_region_begin = option_fill_end; + + uint32_t origin_initial_index = target->fields[origin_idx].initial_idx; + + uint32_t origin_region_ptr = true_origin_region_begin; for (uint32_t it = 0; it < target->field_count; it++) { + if (target->fields[it].initial_idx == origin_initial_index) + continue; + // Fields that end before new_offset can stay there if (target->fields[it].offset + target->fields[it].size <= new_offset) continue; @@ -239,8 +249,8 @@ static void target_swap(struct Target* target, uint32_t origin_idx, const struct origin_region_ptr += falign - (origin_region_ptr % falign); // First field in swap region is exchanged with origin - if (!origin_pulled) { - origin_pulled = 1; + if (!pulled) { + pulled = 1; struct Field tmp = target->fields[it]; target->fields[it] = target->fields[origin_idx]; @@ -259,12 +269,28 @@ static void target_swap(struct Target* target, uint32_t origin_idx, const struct // For all other fields in swap region, pull all until origin_idx one forward and place at origin_idx struct Field tmp = target->fields[it]; - for (uint32_t pull_it = it + 1; pull_it <= origin_idx; pull_it++) - target->fields[pull_it - 1] = target->fields[pull_it]; + if (origin_idx >= it) { + for (uint32_t pull_it = it + 1; pull_it <= origin_idx; pull_it++) + target->fields[pull_it - 1] = target->fields[pull_it]; - target->fields[origin_idx] = tmp; + target->fields[origin_idx] = tmp; + target->fields[origin_idx].offset = origin_region_ptr; + origin_region_ptr += target->fields[origin_idx].size; + } else { + // O X A B C -> pulled=0 + // A X O B C -> pulled=1 + // A B X O C -> pulled=2 + // A B C X O -> pulled=3 + for (uint32_t pull_it = it; pull_it > origin_idx + pulled; pull_it--) + target->fields[pull_it] = target->fields[pull_it - 1]; + + target->fields[origin_idx + pulled] = tmp; + target->fields[origin_idx + pulled].offset = origin_region_ptr; + origin_region_ptr += target->fields[origin_idx + pulled].size; + } + + pulled++; } - print_indices("After swap:", target); } static void target_shuffle_one(struct Target* target) {