Unconditional Recursion

ID

csharp.unconditional_recursion

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

control-flow, reliability

Description

Reports methods whose body unconditionally calls themselves with no base case. A method that recurses on every invocation will overflow the call stack on the first call, producing a StackOverflowException that aborts the process.

Rationale

Recursive methods are written with two parts: a base case that returns directly, and a recursive case that calls the method on a smaller problem. When the base case is missing, the recursive call dominates every path and the method never terminates. This is almost always a forgotten if guard, a missing decrement, or a copy-paste of an existing recursive method without adjusting the exit condition.

The rule fires only on the conservative shape "method body is a single recursive call": either an expression statement, a return of the recursive call, or an expression-bodied method. Recursion guarded by a condition is left to a flow-sensitive analysis.

public int Bad(int n) => Bad(n);                  // FLAW — every call recurses

public void Spin()
{
    Spin();                                       // FLAW — single statement, recursive
}

public int Factorial(int n)
{
    if (n <= 1) return 1;                         // OK — base case present
    return n * Factorial(n - 1);
}

Remediation

Add the missing base case. Verify that every recursive path moves the argument toward the base case (typically a decrement or a structural step), and that the base case returns without recursing.

References