find-infinite-loops

Detects infinite loop risks in PHP code. Finds missing break conditions, incorrect loop variables, unbounded recursion, circular references.

59 stars

Best use case

find-infinite-loops is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Detects infinite loop risks in PHP code. Finds missing break conditions, incorrect loop variables, unbounded recursion, circular references.

Teams using find-infinite-loops should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/find-infinite-loops/SKILL.md --create-dirs "https://raw.githubusercontent.com/dykyi-roman/awesome-claude-code/main/skills/find-infinite-loops/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/find-infinite-loops/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How find-infinite-loops Compares

Feature / Agentfind-infinite-loopsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Detects infinite loop risks in PHP code. Finds missing break conditions, incorrect loop variables, unbounded recursion, circular references.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Infinite Loop Detection

Analyze PHP code for potential infinite loops and unbounded execution.

## Detection Patterns

### 1. Missing Break Conditions

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// BUG: Potentially infinite
$offset = 0;
while (true) {
    $batch = $repository->findBy([], null, 100, $offset);
    if (empty($batch)) {
        break;
    }
    process($batch);
    // Missing: $offset += 100;
}
```

## Grep Patterns

```bash
# 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

```php
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

```php
function traverse($node, array &$visited = []): void
{
    $id = spl_object_id($node);
    if (isset($visited[$id])) {
        return;
    }
    $visited[$id] = true;
    // ...
}
```

### Recursion Depth Limit

```php
function process($data, int $depth = 0): mixed
{
    if ($depth > 100) {
        throw new RuntimeException('Max recursion depth');
    }
    return process($child, $depth + 1);
}
```

## Output Format

```markdown
### 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:**
```php
// With proper termination
```

**Trigger Condition:**
[When this infinite loop would occur]
```

Related Skills

find-type-issues

59
from dykyi-roman/awesome-claude-code

Detects type issues in PHP code. Finds implicit type coercion, mixed types in comparisons, unsafe casting, type mismatches in returns.

find-resource-leaks

59
from dykyi-roman/awesome-claude-code

Detects resource leaks in PHP code. Finds unclosed file handles, database connections not released, streams not freed, missing finally blocks, temporary files not cleaned.

find-race-conditions

59
from dykyi-roman/awesome-claude-code

Detects race conditions in PHP code. Finds shared mutable state, check-then-act patterns, TOCTOU vulnerabilities, concurrent modification issues.

find-null-pointer-issues

59
from dykyi-roman/awesome-claude-code

Detects null pointer issues in PHP code. Finds property/method access on null, missing null checks, nullable returns without handling, optional chaining gaps.

find-logic-errors

59
from dykyi-roman/awesome-claude-code

Detects logic errors in PHP code. Finds incorrect conditions, wrong operators, missing switch cases, inverted logic, short-circuit evaluation issues.

find-exception-issues

59
from dykyi-roman/awesome-claude-code

Detects exception handling issues in PHP code. Finds swallowed exceptions, generic catches, missing exception handling, re-throwing without context, exception in finally.

find-boundary-issues

59
from dykyi-roman/awesome-claude-code

Detects boundary issues in PHP code. Finds array index out of bounds, empty collection access, off-by-one errors, integer overflow, string length issues.

detect-unnecessary-loops

59
from dykyi-roman/awesome-claude-code

Detects unnecessary loop patterns in PHP code. Finds nested loop inefficiency, redundant iterations, in-loop operations that could be batched, loop invariant code.

bug-root-cause-finder

59
from dykyi-roman/awesome-claude-code

Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.

yii-knowledge

59
from dykyi-roman/awesome-claude-code

Yii framework knowledge base. Provides Yii3 modular architecture, DDD integration, PSR-7/PSR-15 compliance, persistence, DI, security (RBAC, auth), event system (PSR-14), queue/jobs, infrastructure components (cache, rate limiter, HTTP client), testing, and antipatterns for Yii PHP projects.

troubleshooting-template

59
from dykyi-roman/awesome-claude-code

Generates troubleshooting guides and FAQ sections for PHP projects. Creates problem-solution documentation.

trace-request-lifecycle

59
from dykyi-roman/awesome-claude-code

Traces full request lifecycle from Router through Middleware, Controller, UseCase, Repository to Response. Documents HTTP methods, routes, middleware stack, response codes, and error handling paths.