A loop that opens something on every pass can run a system out of whatever it opens.
CWE-1050 covers a product that has a loop body or loop condition containing a control element that directly or indirectly consumes platform resources, such as messaging, sessions, locks or file descriptors. MITRE lists it as a Base weakness in any language.
How it happens
The pattern is usually an innocent convenience. Each iteration sends a message, opens a connection or takes a lock, instead of doing that once outside the loop.
# Opens a new connection for every record
for record in records:
conn = db.connect()
conn.insert(record)
conn.close()
# One connection for the whole batch
conn = db.connect()
try:
for record in records:
conn.insert(record)
finally:
conn.close()
MITRE records availability consequences: denial of service through CPU, memory or other resource consumption, and reduced performance. If an attacker can influence the number of iterations, the problem may allow a denial of service. No CVEs are observed.
How to find it
MITRE lists no detection methods. Code review, static analysis rules for resource calls inside loops, and load tests all help. Watch file descriptor counts and connection counts during tests.
How to fix it
MITRE lists no formal mitigations. Reasonable steps:
- Move resource acquisition outside the loop where possible.
- Use pooling and batching.
- Cap the number of iterations that user input can cause.
- Release resources reliably, with finally blocks or scoped constructs.
- Set rate limits and timeouts.
Quick check
When does this become an attack and not just a slow program?
When an attacker can control how many times the loop runs, they can drive resource use to exhaustion.