Aikido

Come identificare e rimuovere il codice morto irraggiungibile

Leggibilità

Regola
Rimuovi il codice morto irraggiungibile
Il codice irraggiungibile è confuso, 
inattestabile 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 rilevano casi evidenti come il codice successivo a istruzioni return o throw. Per i casi complessi, utilizza strumenti di copertura del codice durante i test. Il codice che mostra una copertura pari a zero in suite di test esaustive probabilmente non è raggiungibile, sebbene tu debba verificarlo manualmente poiché potrebbe semplicemente non essere stato testato.

‍

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

Il codice posizionato dopo un'istruzione return in un blocco try ma prima di finally non è raggiungibile. Il blocco finally viene sempre eseguito anche dopo i return. Un bug comune consiste nel posizionare il codice di pulizia dopo il return in un blocco try anziché nel blocco finally, dove verrebbe effettivamente eseguito.

‍

Il codice non raggiungibile CAUSA errori di runtime?

Il codice non raggiungibile È l'errore. Significa che la logica critica che dovrebbe essere eseguita non viene avviata. Se il tuo codice non raggiungibile contiene validazioni, controlli di sicurezza o gestione degli errori, la tua funzione è compromessa anche se non genera eccezioni. Il bug consiste nel fatto che la funzionalità prevista non viene mai eseguita, non che il codice non raggiungibile generi un crash.

‍

Che dire dei feature flag e della compilazione condizionale?

Il codice dietro a feature flag disattivati è comunque raggiungibile a runtime, anche se disabilitato nel tuo ambiente. Il vero codice non raggiungibile è strutturalmente impossibile da eseguire a causa del flusso di controllo. Il codice gestito da feature flag è raggiungibile in modo condizionale e dovrebbe essere mantenuto finché non rimuovi completamente la funzionalità.

‍

Dovrei rimuovere funzioni e import non utilizzati?

Sì, ma si tratta di un problema diverso. Il codice non raggiungibile è strutturalmente impossibile da eseguire all'interno della sua funzione a causa del flusso di controllo. Le funzioni non utilizzate sono richiamabili ma non vengono mai invocate. Entrambi sprecano risorse, ma richiedono strategie di rilevamento differenti. Il rilevamento del codice non raggiungibile opera a livello di singola funzione, mentre il rilevamento del codice non utilizzato richiede un'analisi dell'intero programma.

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.