Aikido

Como detectar e corrigir lógica contraditória em seu código

Bug de lógica

Regra
Detectar contraditório ou impossível lógica
Código que verifica condições após elas 
 violadas violadas, ou presume que
que são impossíveis dado o fluxo fluxo.

Idiomas suportados: 45+

Introdução

Lógica contraditória aparece quando o código verifica condições que já são conhecidas como verdadeiras ou falsas com base em um fluxo de controle anterior. Isso acontece após refatorações, quando a validação é reordenada, ou quando desenvolvedores adicionam verificações defensivas sem entender quais garantias já existem. Uma função que verifica if (user !== null) após chamar user.email possui lógica contraditória, a verificação de nulo chega tarde demais. Essas impossibilidades lógicas indicam problemas mais profundos com a organização do código ou falta de compreensão do que cada caminho de código garante.

Por que isso importa

Implicações de segurança: A validação falsa cria uma perigosa ilusão de segurança. Quando as verificações de segurança aparecem depois que os dados já foram usados, atacantes podem explorar a janela antes que a validação ocorra. O código que valida permissões de usuário após executar operações privilegiadas não oferece proteção real, apenas comentários enganosos sobre segurança.

Manutenibilidade do código: Lógica contraditória sugere que o código não corresponde ao modelo mental do desenvolvedor. Alguém pensou que uma condição precisava ser verificada, mas a colocou no lugar errado, ou o código foi refatorado sem atualizar as verificações relacionadas. Futuros mantenedores não podem confiar que a validação existe onde é necessária, forçando-os a rastrear funções inteiras para entender as garantias reais.

Indicadores de bug: Condições impossíveis raramente existem isoladamente. Elas sinalizam problemas mais profundos, como falta de tratamento de erros, suposições incorretas sobre contratos de função ou refatoração falha. Uma verificação que nunca pode ser executada frequentemente significa que outra verificação está faltando em algum outro lugar que deveria ter prevenido este estado.

Exemplos de código

❌ Não-conforme:

function processOrder(order) {
    if (!order) {
        return { error: 'Order required' };
    }

    const total = order.items.reduce(
        (sum, item) => sum + item.price,
        0
    );

    if (order.items && order.items.length > 0) {
        applyDiscount(order);
    }

    if (total < 0) {
        throw new Error('Invalid total');
    }

    return { total, status: 'processed' };
}

Por que está errado: O código chama order.items.reduce() que falha se os itens forem nulo ou indefinido, então verifica se os itens existem depois. O total < 0 a verificação também é contraditória porque a função reduce sempre retorna valores não negativos ao somar preços.

✅ Compatível:

function processOrder(order) {
    if (!order || !order.items || order.items.length === 0) {
        return { error: 'Valid order with items required' };
    }

    const hasInvalidPrice = order.items.some(
        item => typeof item.price !== 'number' || item.price < 0
    );

    if (hasInvalidPrice) {
        throw new Error('Invalid item prices');
    }

    const total = order.items.reduce(
        (sum, item) => sum + item.price,
        0
    );

    if (order.items.length >= 5) {
        applyBulkDiscount(order);
    }

    return { total, status: 'processed' };
}

Por que isso importa: Toda a validação ocorre antes de usar os dados, as verificações acontecem em ordem lógica e as condições refletem os requisitos reais. A função valida as entradas antecipadamente e, em seguida, processa dados válidos sem verificações redundantes ou contraditórias.

Conclusão

Coloque a validação antes de usar os dados, não depois. Revise as condições que parecem defensivas, mas aparecem depois que os dados já foram acessados ou modificados. Ao refatorar, atualize ou remova a validação relacionada para manter a consistência lógica em toda a função.

FAQs

Dúvidas?

Como distinguir programação defensiva de lógica contraditória?

A programação defensiva valida as entradas nos limites da função antes do uso. A lógica contraditória valida após o uso ou verifica condições já garantidas por código anterior. O momento e a necessidade importam. Se 'user' já foi desreferenciado com 'user.email', então verificar 'if (user)' depois é contraditório, não defensivo.

E quanto ao type narrowing em TypeScript?

A análise de fluxo de controle do TypeScript rastreia o que é possível em cada ponto. Se o TypeScript permite uma verificação, a condição pode ser alcançável. No entanto, o JavaScript em tempo de execução não impõe esses tipos, então verificações contraditórias em tempo de execução ainda podem existir, apesar da segurança de tipo. Concentre-se no fluxo de controle em tempo de execução, não apenas em tipos estáticos.

Lógica contraditória pode causar vulnerabilidades de segurança?

Sim, quando as verificações de segurança ocorrem após a execução de operações privilegiadas. Verificar permissões após gravações no banco de dados, validar a entrada após a execução de uma consulta SQL ou verificar a autenticação após expor dados sensíveis, tudo isso cria vulnerabilidades de tempo de verificação-tempo de uso. A validação deve preceder a ação para que a segurança seja eficaz.

E quanto ao código de tratamento de erro que parece impossível?

Manipuladores de erro para exceções que não podem ocorrer, dada uma validação anterior, podem indicar programação excessivamente defensiva ou tratamento de erros desatualizado de antes da adição da validação. Revise se cada caminho de erro é realmente alcançável. Se impossível, remova-o para simplificar o código e evitar enganar futuros mantenedores.

Como encontrar lógica contraditória em código existente?

Procure por verificações de validação após o acesso aos dados, condições que são sempre verdadeiras ou falsas dadas as ramificações anteriores, e tratamento de erros para estados já prevenidos. Ferramentas de cobertura de código ajudam a identificar ramificações inalcançáveis. A revisão manual de padrões de validação revela verificações que ocorrem tarde demais ou testam condições impossíveis.

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.