Files
Mergen/lifter/memory/MemoryPolicySetup.hpp
yusufcanislek ad41d97112 fix: correctness bugs and inconsistencies in post-lifting passes
GEPLoadPass:
- Check readMemory return value; previously used uninitialized memory
  as a constant replacement on failure (UB + silent miscompile)
- Guard against non-integer load types; getIntegerBitWidth() asserts on
  float/vector/pointer types, causing a crash
- Only process GEPs rooted on the lifter's memory base pointer, not
  arbitrary GEPs created by LLVM optimizations
- Erase replaced LoadInsts and dead GEPs immediately instead of leaving
  dead instructions for the next DCE pass

PromotePseudoStackPass:
- Promote stack accesses both below AND above STACKP_VALUE; previously
  only captured below, missing return address, shadow space, and
  stack-passed arguments
- Use explicit stack bounds [STACKP_VALUE-reserve, STACKP_VALUE+reserve]
  instead of isConcrete(), which would also capture PE image sections
  and create a multi-gigabyte alloca
- Add stackReserve field to lifter class, set by configureDefaultMemoryPolicy
- Guard against unsigned underflow in stackLower computation

ReplaceTruncWithLoadPass:
- Generalize from hardcoded i64->i32 to any integer narrowing; now also
  handles i32->i16, i16->i8, etc.
- Erase original wide LoadInst when it has no remaining users

Stack bounds consistency:
- pageMap (markMemPaged/isMemPaged) now uses clamped stack reserve from
  lifter->stackReserve instead of raw PE header value, so pageMap,
  memoryPolicy, and PromotePseudoStackPass all agree on stack bounds
- Changed pageMap, markMemPaged, isMemPaged from int64_t to uint64_t
  to match the actual address types and avoid signed/unsigned mismatch

Cleanup:
- Remove dead final_optpass declaration from PathSolver.h (no impl/callers)
- Remove fragile name-based 'memory' argument fallback in run_opts;
  assert memoryAlloc is set instead
2026-03-26 11:46:03 +03:00

31 lines
1.3 KiB
C++

#pragma once
#include "LifterClass_Concolic.hpp"
#include <algorithm>
#include <cstdint>
inline void configureDefaultMemoryPolicy(lifterConcolic<>* lifter,
uint64_t stackReserve = 0x1000) {
lifter->memoryPolicy.setDefaultMode(MemoryAccessMode::SYMBOLIC);
for (auto& section : lifter->file.sections_v) {
const auto sectionStart = lifter->file.imageBase + section.virtual_address;
const auto sectionEnd = sectionStart + section.virtual_size;
// All PE sections are CONCRETE: initial values are known from the file.
// The concolic buffer tracks stores, so reads without prior stores
// correctly return the file's initial bytes.
lifter->memoryPolicy.addRange(sectionStart, sectionEnd,
MemoryAccessMode::CONCRETE);
}
// Use actual stack reserve from PE header instead of hardcoded 0x1000.
// Clamp to reasonable bounds: at least 0x1000, at most 0x100000 (1MB).
uint64_t clampedReserve = std::max(stackReserve, uint64_t(0x1000));
clampedReserve = std::min(clampedReserve, uint64_t(0x100000));
lifter->stackReserve = clampedReserve;
lifter->memoryPolicy.addRange(STACKP_VALUE - clampedReserve,
STACKP_VALUE + clampedReserve,
MemoryAccessMode::CONCRETE);
}