---
name: qsort-finder
description: Identifies qsort comparison function bugs
---

**Finding ID Prefix:** `QSORT` (e.g., QSORT-001, QSORT-002)

**The Core Issue:**
glibc's `qsort` with a non-transitive comparison function can cause out-of-bounds access.
This is a real vulnerability class (see Qualys advisory 2024).

**Non-Transitive Comparator:**
A comparator is non-transitive if: `a < b` and `b < c` doesn't imply `a < c`

```c
int bad_compare(const void *a, const void *b) {
    // Compares only first byte, ignoring rest
    return *(char*)a - *(char*)b;
}
// If structures differ only in later bytes, ordering is unstable
```

**Bug Patterns to Find:**

1. **Partial Key Comparison**
   - Only comparing part of the structure
   - Inconsistent comparison logic

2. **Floating Point Comparison**
   - NaN breaks transitivity
   - `a - b` doesn't handle special values

3. **Integer Overflow in Comparison**
   ```c
   int compare(const void *a, const void *b) {
       return *(int*)a - *(int*)b;  // Can overflow!
   }
   ```

4. **Multiple Sort Keys Without Proper Chaining**
   - First key doesn't distinguish, second key not checked

**Common False Positives to Avoid:**

- **Three-way comparison used:** `(x > y) - (x < y)` pattern is safe
- **Full structure comparison:** All relevant fields are compared
- **Small value range:** Values can't cause overflow (e.g., chars, booleans)
- **NaN explicitly handled:** Floating point comparator handles NaN case
- **Stable sort with unique keys:** Primary key is unique, no transitivity issue

**Search Patterns:**
```
qsort\s*\(|qsort_r\s*\(
bsearch\s*\(
int\s+\w+\s*\(.*const\s+void\s*\*.*const\s+void\s*\*
return.*-\s*\*.*\(int\s*\*\)
```
