Awesome-claude-code find-infinite-loops
Detects infinite loop risks in PHP code. Finds missing break conditions, incorrect loop variables, unbounded recursion, circular references.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/find-infinite-loops" ~/.claude/skills/dykyi-roman-awesome-claude-code-find-infinite-loops && rm -rf "$T"
manifest:
skills/find-infinite-loops/SKILL.mdsource content
Infinite Loop Detection
Analyze PHP code for potential infinite loops and unbounded execution.
Detection Patterns
1. Missing Break Conditions
// BUG: No exit condition while (true) { $item = $queue->pop(); process($item); // No break when queue is empty } // BUG: Condition never changes $running = true; while ($running) { doWork(); // $running never set to false } // BUG: Break inside nested condition while ($items) { foreach ($items as $item) { if ($item->isDone()) { break; // Only breaks inner loop } } }
2. Incorrect Loop Variable Modification
// BUG: Wrong variable incremented for ($i = 0; $i < count($items); $j++) { // Should be $i++ process($items[$i]); } // BUG: Variable modified in wrong direction for ($i = 10; $i > 0; $i++) { // Should be $i-- process($i); } // BUG: Loop variable reset $i = 0; while ($i < 10) { if ($condition) { $i = 0; // Resets counter } $i++; }
3. Unbounded Recursion
// BUG: No base case function factorial(int $n): int { return $n * factorial($n - 1); // Never stops } // BUG: Base case unreachable function traverse(Node $node): void { $this->traverse($node->getNext()); // What if getNext returns self? // Missing: if ($node === null) return; } // BUG: Mutual recursion function a($n) { return b($n); } function b($n) { return a($n); } // Infinite cycle
4. Circular References
// BUG: Circular linked list traversal while ($node !== null) { $node = $node->next; // What if list is circular? } // BUG: Object graph cycle function serialize($obj, $visited = []): string { foreach ($obj->getRelations() as $rel) { $result .= serialize($rel); // May revisit objects } } // FIXED: function serialize($obj, array &$visited = []): string { if (in_array($obj, $visited, true)) { return '[circular]'; } $visited[] = $obj; // ... }
5. Event/Listener Loops
// BUG: Event triggers itself class UserUpdatedListener { public function handle(UserUpdated $event): void { $user = $event->getUser(); $user->touch(); // Triggers another UserUpdated event } } // BUG: Message queue requeue loop public function handle(Message $message): void { try { $this->process($message); } catch (Exception $e) { $this->queue->publish($message); // Requeues failed message infinitely } }
6. Retry Without Limit
// BUG: Infinite retry function fetch(string $url): string { while (true) { try { return $this->httpClient->get($url); } catch (Exception $e) { sleep(1); // No max retries, infinite loop on persistent failure } } } // FIXED: function fetch(string $url, int $maxRetries = 3): string { $attempts = 0; while ($attempts < $maxRetries) { try { return $this->httpClient->get($url); } catch (Exception $e) { $attempts++; if ($attempts >= $maxRetries) { throw $e; } sleep(1); } } }
7. Generator Infinite Yield
// BUG: Generator never ends function allNumbers(): Generator { $i = 0; while (true) { yield $i++; // Fine for generators, but consuming code may not limit } } // Usage BUG: foreach (allNumbers() as $n) { echo $n; // Infinite loop }
8. Database Pagination Without Limit
// BUG: Potentially infinite $offset = 0; while (true) { $batch = $repository->findBy([], null, 100, $offset); if (empty($batch)) { break; } process($batch); // Missing: $offset += 100; }
Grep Patterns
# while(true) without break Grep: "while\s*\(\s*true\s*\)" --glob "**/*.php" # Recursion Grep: "function\s+(\w+)\([^)]*\)[^{]*\{[^}]*\1\s*\(" --glob "**/*.php" # for loop with wrong increment Grep: "for\s*\([^;]+;\s*\$\w+\s*[<>]\s*[^;]+;\s*\$(?!\1)" --glob "**/*.php" # while without modification Grep: "while\s*\(\s*\$\w+\s*\)" --glob "**/*.php"
Severity Classification
| Pattern | Severity |
|---|---|
| Infinite retry without limit | 🔴 Critical |
| Missing recursion base case | 🔴 Critical |
| Wrong loop variable | 🔴 Critical |
| Circular reference traversal | 🟠 Major |
| Event self-triggering | 🟠 Major |
| while(true) without clear exit | 🟠 Major |
Prevention Patterns
Always Use Limits
const MAX_ITERATIONS = 1000; $iterations = 0; while ($condition && $iterations < self::MAX_ITERATIONS) { // ... $iterations++; } if ($iterations >= self::MAX_ITERATIONS) { throw new RuntimeException('Max iterations exceeded'); }
Track Visited Nodes
function traverse($node, array &$visited = []): void { $id = spl_object_id($node); if (isset($visited[$id])) { return; } $visited[$id] = true; // ... }
Recursion Depth Limit
function process($data, int $depth = 0): mixed { if ($depth > 100) { throw new RuntimeException('Max recursion depth'); } return process($child, $depth + 1); }
Output Format
### Infinite Loop Risk: [Description] **Severity:** 🔴/🟠/🟡 **Location:** `file.php:line` **Type:** [Missing Break|Wrong Variable|Unbounded Recursion|...] **Issue:** [Description of how infinite loop can occur] **Code:** ```php // Problematic code
Fix:
// With proper termination
Trigger Condition: [When this infinite loop would occur]