終了条件がない再帰呼び出し

終了条件がない再帰呼び出し

説明

明確な終了条件がないまま自身を呼び出す再帰関数は、入力によってコールスタックを使い果たしたり、実行が終わらなくなったりする場合があります。外部から呼び出せる経路では、入力やリクエスト量に応じてサービスの可用性にも影響するおそれがあります。

想定される影響

  • スタックの枯渇や終わらない実行で、プログラムが停止する可能性があります。
  • 入力範囲によって、処理時間やリソース使用量を予測しにくくなる場合があります。

対処方法

  • 再帰呼び出しの前に、終了条件と入力範囲を検証してください。
  • 再帰の深さを制限するか、反復処理へ変更してください。

例

変更前

javascript
function factorial(x) {
  return x * factorial(x - 1);
}

変更後

javascript
function factorial(x) {
  if (!Number.isInteger(x) || x < 0 || x > 18) {
    throw new RangeError("unsupported input");
  }
  if (x <= 1) {
    return 1;
  }
  return x * factorial(x - 1);
}

解説:

  • 変更前: 呼び出しを止める終了条件がなく、スタックを使い果たすおそれがあります。
  • 変更後: 入力範囲を検証し、基底条件で処理を終了します。上限18は、階乗を Number の安全な整数範囲で計算するための例です。より大きな整数が必要なら、適切な数値表現とリソース制限を使ってください。

参考資料