Aikido

Come identificare e rimuovere il codice morto irraggiungibile

Leggibilità

Regola
Rimuovi il codice morto
non raggiungibile. Ilcodice non
raggiungibile è confuso, non

testabile e dovrebbe essere rimosso. Linguaggi supportati: 45+

Introduzione

Il codice irraggiungibile segnala una logica compromessa nella tua codebase. Il codice successivo a return oppure throw È stato scritto del codice destinato all'esecuzione che però non viene mai eseguito. Le condizioni sempre false celano validazioni o gestioni degli errori che non si attivano mai. I rami che la logica non raggiunge mai a causa del flusso di controllo contengono funzionalità che non possono essere eseguite. Quando trovi del codice non raggiungibile, hai scoperto un bug in cui il codice non sta facendo ciò per cui era stato progettato.

Perché è importante

Vulnerabilità di sicurezza: I controlli di sicurezza non raggiungibili non proteggono la tua applicazione. Se l'autenticazione, l'autorizzazione o la validazione dell'input compaiono dopo un return istruzione, il tuo codice sembra sicuro ma non lo è. Gli aggressori possono sfruttare funzioni che sembrano dotate di misure di sicurezza ma che in realtà le aggirano. La code review potrebbe non individuare queste vulnerabilità perché la logica di sicurezza esiste nella codebase, ma non viene mai eseguita.

Bug logici in produzione: Il codice morto indica che la tua funzione non sta implementando la logica che pensavi. Una validazione che non viene mai eseguita lascia passare dati non validi. Una gestione degli errori non raggiungibile significa che gli errori si propagano senza essere intercettati. Le regole di business che vengono aggirate producono risultati errati. Il codice sembra corretto ma si comporta in modo diverso da quello previsto. Lacune nei test: Il codice non raggiungibile non può essere testato. Se la tua suite di test viene superata nonostante codice critico risulti non raggiungibile, significa che non disponi di test che coprono quei percorsi. Il codice non raggiungibile rivela lacune nella copertura dei test, laddove esiste una logica importante priva di test che ne verifichino l'esecuzione.

Impatto sulle dimensioni del bundle: Il codice non raggiungibile viene comunque distribuito agli utenti come peso morto nel bundle JavaScript. Gli utenti scaricano ed eseguono il parsing di codice che non viene mai eseguito, sebbene questo sia un aspetto secondario rispetto ai bug logici segnalati dal codice morto.

Esempi di codice

❌ Non conforme:

function transferFunds(fromAccount, toAccount, amount) {
    if (!fromAccount || !toAccount) {
        return { success: false, error: 'Invalid accounts' };
    }

    if (amount <= 0) {
        return { success: false, error: 'Invalid amount' };
        logSuspiciousActivity(fromAccount, amount);
    }

    const balance = getBalance(fromAccount);
    if (balance >= amount) {
        deductFunds(fromAccount, amount);
        addFunds(toAccount, amount);
        return { success: true };
    }

    return { success: false, error: 'Insufficient funds' };

    // Check for fraud patterns
    if (isHighRiskTransaction(fromAccount, toAccount, amount)) {
        notifyFraudTeam(fromAccount, toAccount, amount);
        return { success: false, error: 'Transaction blocked' };
    }
}

Perché è errato: La logica di rilevamento delle frodi non viene mai eseguita perché la funzione restituisce un valore prima di raggiungerla. Anche la registrazione delle attività sospette successiva al controllo dell'importo non viene mai eseguita. Questa funzione sembra disporre di misure di sicurezza, ma in realtà elabora tutti i trasferimenti senza effettuare controlli antifrode.

✅ Conforme:

function transferFunds(fromAccount, toAccount, amount) {
    if (!fromAccount || !toAccount) {
        return { success: false, error: 'Invalid accounts' };
    }

    if (amount <= 0) {
        logSuspiciousActivity(fromAccount, amount);
        return { success: false, error: 'Invalid amount' };
    }

    if (isHighRiskTransaction(fromAccount, toAccount, amount)) {
        notifyFraudTeam(fromAccount, toAccount, amount);
        return { success: false, error: 'Transaction blocked' };
    }

    const balance = getBalance(fromAccount);
    if (balance >= amount) {
        deductFunds(fromAccount, amount);
        addFunds(toAccount, amount);
        return { success: true };
    }

    return { success: false, error: 'Insufficient funds' };
}

Perché questo è importante: Tutti i controlli di sicurezza vengono eseguiti prima di elaborare il trasferimento. Il rilevamento delle frodi viene eseguito su ogni transazione. Le attività sospette vengono registrate. La funzione implementa effettivamente la logica di sicurezza che sembra avere.

Conclusione

Il codice non raggiungibile indica la presenza di bug nella logica in cui la funzionalità prevista non viene mai eseguita. Individuvalo tramite strumenti di analisi statica nella tua pipeline CI e trattalo come un problema critico, non come una semplice pulizia del codice. Quando scopri del codice non raggiungibile, indaga sul motivo della sua presenza e su quale logica avrebbe dovuto essere eseguita ma non lo è.

FAQ

Hai domande?

Come posso identificare il codice non raggiungibile in codebase di grandi dimensioni?

Gli strumenti di analisi statica possono rilevare casi ovvi come il codice posizionato dopo le istruzioni return o throw. Per i casi più complessi, utilizza gli strumenti di code coverage durante i test. Il codice che mostra una copertura pari a zero in tutte le esecuzioni dei test potrebbe non essere raggiungibile. Esamina ciascun caso manualmente, poiché parte del codice potrebbe essere raggiungibile ma semplicemente non testata.

‍

Cosa dire del codice situato dopo i return anticipati nei blocchi try-catch?

Il codice inserito dopo un'istruzione return in un blocco try ma prima di finally non è raggiungibile. Tuttavia, i blocchi finally vengono sempre eseguiti anche dopo le istruzioni return. Un errore comune consiste nel posizionare importanti operazioni di pulizia (cleanup) dopo un return in un blocco try anziché nel blocco finally, dove verrebbero effettivamente eseguite.

‍

Il codice non raggiungibile CAUSA errori di runtime?

No, perché non viene mai eseguito. Tuttavia, può fare riferimento a variabili non definite o chiamare funzioni inesistenti senza causare errori, il che lo rende ancora più insidioso. Questo codice difettoso supera tutti i test perché non viene mai eseguito, ma trae in inganno chiunque legga la codebase.

‍

Che dire dei feature flag e della compilazione condizionale?

Il codice associato a feature flag disattivate risulta accessibile a runtime, anche se disabilitato nell'ambiente corrente. Il vero codice irraggiungibile è strutturalmente impossibile da eseguire a causa del flusso di controllo. Il codice regolato da feature flag è condizionatamente raggiungibile e dovrebbe rimanere tale finché la funzionalità non viene completamente rimossa.

‍

Dovrei rimuovere funzioni e import non utilizzati?

Sì, ma si tratta di una categoria diversa di codice morto. Il codice irraggiungibile è strutturalmente impossibile da eseguire a causa del flusso di controllo. Le funzioni non utilizzate sono raggiungibili ma non vengono mai chiamate. Entrambi dovrebbero essere rimossi, ma richiedono strategie di rilevamento differenti. Il rilevamento del codice non utilizzato richiede un'analisi dell'intero programma, mentre il rilevamento del codice irraggiungibile opera a livello di singola funzione.

Metti in sicurezza ora

Metti in sicurezza il tuo codice, il cloud e il runtime in un unico sistema centralizzato.
Trova e risolvi le vulnerabilità rapidamente e automaticamente.

Nessuna carta di credito richiesta | Risultati della scansione in 32 secondi.