mirror of
https://github.com/lifting-bits/sleigh
synced 2026-06-21 13:56:12 +00:00
2.5 KiB
2.5 KiB
Common Bug Patterns in Ghidra Decompiler Source
Strict-weak ordering violations
The most common class of bugs caught by libc++ assertions. A comparator for
std::sort or std::set must satisfy:
- Irreflexivity:
comp(a, a)must returnfalse - Asymmetry: if
comp(a, b)is true thencomp(b, a)must be false - Transitivity: if
comp(a, b)andcomp(b, c)thencomp(a, c)
The libc++ assertion message looks like:
strict_weak_ordering_check.h:50: libc++ Hardening assertion
!__comp(*(__first + __a), *(__first + __b)) failed:
Your comparator is not a valid strict-weak ordering
Pattern 1: Null pointer sentinel without self-check
// BUG: when both are null, returns true (violates irreflexivity)
if (ptr == nullptr)
return true;
// FIX: only return true when the other is non-null
if (ptr == nullptr)
return (other.ptr != nullptr);
Real example: PullRecord::operator< in bitfield.cc — when both readOp
pointers were null, the comparator returned true.
Pattern 2: Special index without self-check
// BUG: when comparing the entry point with itself, returns true
if (bl1->getIndex() == 0) return true;
// FIX: check that the other is different
if (bl1->getIndex() == 0) return (bl2->getIndex() != 0);
Real example: FlowBlock::compareFinalOrder in block.cc.
Pattern 3: Unsafe cast in compareDependency (TypePartial* classes)
The TypePartialEnum, TypePartialStruct, and TypePartialUnion classes have
compareDependency methods that cast op to their own type. If op is actually
the parent container type (not a partial), the cast accesses invalid memory.
// BUG: casts op to TypePartialFoo without checking if op IS the container
TypePartialFoo *tp = (TypePartialFoo *) &op;
// FIX: add a guard before the cast
if (container == &op) return 1; // op is our container
TypePartialFoo *tp = (TypePartialFoo *) &op;
Real example: TypePartialEnum::compareDependency in type.cc (patched in 0005).
How to audit comparators systematically
- Search for all
operator<,::compare, and::compareDependencyfunctions - Search for all
sort(,stable_sort(, andstd::setusage to find which comparators are actually used in sorting contexts - For each comparator, mentally trace the case where both arguments are identical — does it return false?
- Check for early-return branches that don't verify the other operand differs
- For
compareDependencymethods in TypePartial* classes, check for the container-guard pattern before unsafe casts