java-topology/defects/xtuple-0001/TICKET.md
russell@unturf.com 6f11fb7598 xtuple: 5-MOAD scan; xtuple-0001 CWE-407 orutils missingParamList QStringList::contains O(P*M) 52x at P=1000
Scanned xTuple OpenRPT (public C++/Qt report engine used by xTuple ERP).
One MOAD-0001 defect found in orutils.cpp SQL parameter parsing loop.
MOADs 0002/0003/0004/0005 CLEAN.
2026-04-03 14:01:48 -04:00

61 lines
1.9 KiB
Markdown

# xtuple-0001: orutils.cpp missingParamList QStringList::contains O(P*M) in SQL param parse loop
**Project:** xTuple / OpenRPT (open-source ERP report engine)
**File:** `OpenRPT/renderer/orutils.cpp`
**MOAD:** 0001 (CWE-407 — Inefficient Algorithmic Complexity)
**Severity:** LOW-MEDIUM
**Speedup:** ~10-50x at P=1000, M=500
## Description
`orQuery::orQuery()` parses a SQL string to find parameter placeholders
(`$"name"` and `%N` style). As it encounters each placeholder, it checks
whether the parameter name is already in `missingParamList` before appending:
```cpp
// OpenRPT/renderer/orutils.cpp:65
if(!missingParamList.contains(n))
missingParamList.append(n);
```
`missingParamList` is declared as `QStringList` (i.e. `QList<QString>`).
`QStringList::contains()` is a linear O(M) scan where M is our current missing
param count. The outer loop iterates P times (once per param placeholder in
the SQL). Total complexity: O(P * M).
For a parametric report template with hundreds of placeholder occurrences and
many distinct missing params (e.g., a batch report runner that pre-scans many
SQL templates), this compounds into measurable overhead.
## Fix
Replace the membership check with a `QSet<QString>` shadow set for O(1)
average-case lookup, while keeping `missingParamList` as the ordered
`QStringList` for downstream consumption (it is a public member used by
callers to display ordered missing-param dialogs).
```cpp
QSet<QString> missingParamSet;
// ...
if(!missingParamSet.contains(n)) {
missingParamSet.insert(n);
missingParamList.append(n);
}
```
## Complexity
| Version | Time |
|---------|------|
| Before | O(P * M) |
| After | O(P) amortized |
## Affected File
`OpenRPT/renderer/orutils.cpp` (and `orutils.h` for the shadow set field)
## Test
`defects/xtuple-0001/test/test_xtuple_0001.py` — simulates the pattern in
Python, benchmarks N=1000 param slots with M=500 distinct missing params,
asserts speedup > 3x.