44 lines
1.4 KiB
Markdown
44 lines
1.4 KiB
Markdown
# UNDF: UNDF-2026-000000376
|
|
## Classification
|
|
|
|
| Field | Value |
|
|
|-------------|-------|
|
|
| CWE | CWE-407 Inefficient Algorithmic Complexity |
|
|
| Severity | MEDIUM |
|
|
| Component | `net/minecraft/world/level/block/piston/PistonStructureResolver.java` |
|
|
| Function | `resolve()` BFS loop |
|
|
| Hot path | Called every piston activation event |
|
|
|
|
## Defect
|
|
|
|
`PistonStructureResolver.toPush` is an `ArrayList<BlockPos>`. During piston
|
|
BFS, `toPush.contains(pos)` is called for every candidate block — O(N) scan
|
|
per call, inside the BFS loop: O(N²) total.
|
|
|
|
```java
|
|
// BEFORE — O(N²): ArrayList.contains() inside BFS loop
|
|
private final List<BlockPos> toPush = Lists.newArrayList();
|
|
// ...
|
|
if (!this.toPush.contains(pos)) {
|
|
this.toPush.add(pos);
|
|
}
|
|
```
|
|
|
|
At the 12-block push limit toPush is bounded, but the pattern propagates
|
|
to modded environments with higher push limits.
|
|
|
|
## Fix
|
|
|
|
Add a parallel `HashSet<BlockPos>` for O(1) duplicate detection.
|
|
|
|
```java
|
|
// AFTER — O(N): HashSet.add() returns false on duplicate → O(1)
|
|
private final List<BlockPos> toPush = Lists.newArrayList();
|
|
private final Set<BlockPos> toPushSet = new HashSet<>();
|
|
|
|
// Replace: if (!this.toPush.contains(pos)) { this.toPush.add(pos); }
|
|
// With: if (this.toPushSet.add(pos)) { this.toPush.add(pos); }
|
|
```
|
|
|
|
The `List` is retained for ordered iteration (piston push order matters).
|
|
The `Set` is used only for membership testing.
|