Documentazione
/

Risoluzione dei problemi

/

Evitare le collisioni di identificatori

Evitare le collisioni di identificatori tra file offuscati

Quando più file offuscati con la VM finiscono nello stesso bundle, possono dichiarare lo stesso identificatore di primo livello e far fallire la pagina in fase di parsing. Ecco perché succede e come risolverlo.

Il sintomo

La build viene eseguita senza problemi, ma il browser genera un errore in fase di parsing, prima dell'avvio dell'app:

Testo

Per vedere quanti chunk dichiarano il nome indicato nell'errore, conta i file che ne contengono una dichiarazione:

Testo

-l elenca ogni file corrispondente una sola volta e -w trova solo parole intere, quindi vmdX non viene conteggiato. var è escluso perché ripetere una dichiarazione var di per sé non è un errore. Un risultato maggiore di 1 significa che il nome è dichiarato in più di un chunk. Sostituisci vmd con il nome presente nel tuo messaggio di errore.

Le collisioni di identificatori contano solo quando le dichiarazioni condividono uno scope. Lo stesso nome ripetuto in moduli o closure separati non prova una collisione; l'errore di parsing qui sopra sì.

Perché succede

I preset VM usano mangled-shuffled come Identifier Names Generator. Percorre un piccolo alfabeto in un ordine mescolato e, con l'offuscamento VM, ogni variabile globale rinominata riceve un prefisso vm (aggiunto davanti a qualsiasi identifiersPrefix impostato, quindi checkout_ diventa vm_checkout_...). L'ordine mescolato viene memorizzato in cache per processo, quindi i file offuscati nello stesso processo, o con lo stesso seed fisso, attingono alla stessa sequenza: la prima variabile globale di ogni file ha lo stesso nome, la seconda ne condivide un altro, e così via.

Ogni file viene offuscato in modo indipendente e il generatore riparte dall'inizio della sua sequenza per ciascuno di essi. Quando due file finiscono nello stesso scope, i nomi entrano in collisione. Due dichiarazioni di primo livello let vmd finiscono nello stesso scope e il parser rifiuta la seconda.

Ogni file offuscato con la VM dichiara un nome di runtime di primo livello senza suffisso, e questo basta per una collisione. renameGlobals: true peggiora molto le cose: ogni dichiarazione di primo livello diventa un breve nome vm* e i nomi propri del runtime perdono il loro suffisso univoco.

Soluzioni

Se possibile, esegui prima il bundling e poi offusca il bundle una sola volta. Se invece offuschi i file separatamente e gli script condividono uno scope globale, scegli una delle seguenti soluzioni:

  • Attiva randomIdentifiersPrefix (consigliato)

    Ogni esecuzione dell'offuscamento riceve un prefisso casuale anteposto a ogni identificatore globale (con l'offuscamento VM sostituisce il prefisso predefinito vm). I nomi di file diversi non condividono più uno spazio dei nomi, quindi le collisioni scompaiono senza che tu debba coordinare manualmente i prefissi.

  • Imposta un identifiersPrefix univoco per ogni file

    Passa manualmente un prefisso diverso quando offuschi ciascun file (ad esempio identifiersPrefix: 'auth_' per uno, checkout_ per un altro). È efficace, ma soggetto a errori se hai molti file: preferisci l'opzione casuale descritta sopra.

    JavaScript

  • Imposta identifierNamesGenerator su hexadecimal

    I nomi esadecimali usano uno spazio di chiavi molto più ampio, quindi è molto meno probabile che due file producano lo stesso identificatore, ma l'univocità non è garantita. Compromesso: gli identificatori sono più lunghi dell'output di mangled-shuffled, quindi il bundle è leggermente più grande.

  • Usa l'interfaccia di elaborazione multi-file o verifica il plugin del bundler

    La dashboard aggiunge un prefisso distinto a ogni file all'interno di uno stesso batch multi-file (piani a pagamento); i file di batch separati possono comunque entrare in collisione. Se usi un plugin del bundler, verifica il suo comportamento invece di dare per scontato che faccia lo stesso. Se chiami tu stesso il pacchetto javascript-obfuscator o l'API, devi attivare un prefisso.

Per verificare la correzione, ricompila e ricarica l'applicazione combinata e conferma che il SyntaxError sia scomparso. Il nome presente nel vecchio messaggio di errore non dovrebbe più essere dichiarato in più di un chunk; un prefisso cambia ogni nome generato, quindi il comando grep qui sopra ti informa solo su quel nome specifico, non su quelli nuovi.

Opzioni correlate