# empty array inputs bypass loop-based verification entirely when callers omit array length validation
Loop-based verification is common in multi-signature systems and batch operations: iterate over an array and confirm each element meets a condition. With an empty array, a `for` loop runs zero iterations, every check is skipped, and the function exits believing all inputs were valid. This is vacuous truth, and it is exploitable: an attacker passes `[]` and proceeds with full authorization.
The pattern generalizes beyond signatures to any loop-based check: access control lists, whitelist verifications, parameter validation sets. Since [[developer subconscious assumptions about prior state create systematic input validation gaps auditors must explicitly hunt]], auditors should flag any function whose security depends on at least one successful loop iteration. The fix is a pre-loop assertion: `require(inputs.length > 0)` or `require(signatures.length >= threshold)`.
This connects to a broader class of silent bypasses. Since [[silent semantic mismatch is a cross-language vulnerability class where code appears to enforce constraints but silently fails]], the empty-array bypass is an application-layer instance. The same zero-input structure appears at the compiler level: since [[vyper compiler side effect elision skips state-changing expressions when slice or concat receives zero-length arguments]], zero-length arguments cause the compiler to skip operations. It recurs in test infrastructure: since [[Foundry's invariant fuzzer silently reports success when all function calls revert indicating it validates harness health not protocol correctness]], zero successful calls produce vacuous passing results.
The complementary failure exists at the other extreme: since [[off-by-one errors in loop bounds and comparison operators cause silent boundary failures]], auditors should test both zero-element bypass and off-by-one at the upper bound. A parallel exists in threshold checks: since [[slippage protection with zero minTokensOut exposes users to unlimited loss and must always be flagged as critical in audits]], setting a minimum to zero neutralizes the guard by the same logic.
Relevant Notes:
- [[developer subconscious assumptions about prior state create systematic input validation gaps auditors must explicitly hunt]]: the meta-pattern this exemplifies: the implicit assumption "caller provides at least one element" is never encoded as an explicit precondition
- [[two-step ownership transfer is exploitable when step two does not verify step one was initiated]]: sibling assumption-exploitation pattern from the same source: unchecked step ordering instead of unchecked array length
- [[silent semantic mismatch is a cross-language vulnerability class where code appears to enforce constraints but silently fails]]: exemplifies: the empty-array bypass is an application-layer instance where verification loops appear to enforce constraints but silently pass with zero elements
- [[vyper compiler side effect elision skips state-changing expressions when slice or concat receives zero-length arguments]]: structural parallel at the compiler layer: zero-length input causes expected operations to be silently skipped, same zero-input bypass logic at a different abstraction level
- [[Foundry's invariant fuzzer silently reports success when all function calls revert indicating it validates harness health not protocol correctness]]: structural parallel in test infrastructure: zero successful executions produce vacuous passing results by the same logical mechanism
- [[off-by-one errors in loop bounds and comparison operators cause silent boundary failures]]: sibling loop-boundary failure class: wrong bounds (one too many or too few) versus zero-iteration bypass; auditors should test both ends of the array-size spectrum
- [[slippage protection with zero minTokensOut exposes users to unlimited loss and must always be flagged as critical in audits]]: sibling in the zero-threshold bypass class: a numeric minimum set to zero makes a protective require trivially pass, same "minimum neutralized to zero" logic applied to numeric thresholds instead of loop counts
Topics:
- [[vulnerability-patterns]]