Regra
Evite recursão sem proteção proteção.
Recursão sem proteção limitação limitação riscos pilha
transbordamento e cria DoS vulnerabilidades a partir de entradas
entradas. Recursão com profundidade limites e e limites
limites verificação é aceitável.
Suporte a idiomas: 45+Introdução
Funções recursivas sem limites de profundidade podem esgotar a pilha de chamadas (call stack), causando falhas. Entradas maliciosas, como objetos JSON profundamente aninhados ou estruturas de dados cíclicas, podem desencadear recursão ilimitada intencionalmente. Uma única requisição maliciosa pode derrubar seu serviço ao exceder os limites da pilha, criando uma vulnerabilidade de negação de serviço (denial-of-service) trivial de explorar.
Por que isso importa
Implicações de segurança (ataques DoS): Atacantes podem criar entradas que desencadeiam recursão profunda, travando sua aplicação. JSON, XML ou estruturas de dados aninhadas profundamente são vetores de ataque comuns. Uma única requisição maliciosa esgota a pilha, derrubando todo o serviço para todos os usuários.
Estabilidade do sistema: Erros de stack overflow travam o processo imediatamente sem degradação elegante. Em produção, isso significa requisições perdidas, transações interrompidas e indisponibilidade do serviço. A recuperação exige reiniciar a aplicação inteira.
Esgotamento de recursos: A recursão ilimitada consome memória da pilha exponencialmente. Cada chamada recursiva adiciona um frame à pilha, e cadeias de recursão profundas podem consumir megabytes de memória. Isso afeta outros processos no mesmo servidor e pode desencadear condições de falta de memória.
Exemplos de código
❌ Não-conforme:
function processNestedData(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const result = {};
for (const key in obj) {
result[key] = processNestedData(obj[key]);
}
return result;
}Por que está errado: Nenhum limite de profundidade permite que invasores enviem objetos profundamente aninhados que excedem os limites da pilha. Entrada como {a: {a: {a: {...}}}} aninhado a 10.000 níveis de profundidade trava a aplicação com estouro de pilha (stack overflow). A função recursa cegamente sem verificar a profundidade.
✅ Compatível:
function processNestedData(obj, depth = 0, maxDepth = 100) {
if (depth > maxDepth) {
throw new Error('Maximum nesting depth exceeded');
}
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const result = {};
for (const key in obj) {
result[key] = processNestedData(obj[key], depth + 1, maxDepth);
}
return result;
}Por que isso importa: O maxDepth o parâmetro limita a recursão a 100 níveis, prevenindo estouro de pilha (stack overflow). Este limite é alto o suficiente para estruturas de dados aninhadas legítimas (a maioria dos dados do mundo real raramente excede 10-20 níveis), ao mesmo tempo em que é baixo o suficiente para interromper ataques antes de consumir uma quantidade significativa de memória da pilha. Entradas maliciosas profundamente aninhadas geram um erro em vez de travar a aplicação. A verificação de profundidade ocorre antes do processamento, falhando rapidamente quando os limites são excedidos.
Conclusão
Adicione parâmetros de profundidade a todas as funções recursivas que processam dados externos. Defina profundidades máximas razoáveis com base na complexidade esperada da estrutura de dados. Lance erros ou retorne valores padrão quando os limites de profundidade forem excedidos em vez de falhar.
.avif)
