Sono a conoscenza di Denial of Service (ReDoS) di espressioni regolari. Esiste un modo ragionevole per consentire agli utenti di creare regex personalizzate garantendo al contempo di non presentare un pattern esponenzialmente lento?
Sono a conoscenza di Denial of Service (ReDoS) di espressioni regolari. Esiste un modo ragionevole per consentire agli utenti di creare regex personalizzate garantendo al contempo di non presentare un pattern esponenzialmente lento?
Risposte:
Il problema con le espressioni regolari non è la regex stessa, ma che il motore regex ha tutti i tipi di funzionalità "convenienti" come il backtracking. Pertanto, l'utilizzo di un motore regex senza queste funzionalità evita.
Le espressioni regolari del concetto di informatica possono sempre essere abbinate in tempo lineare dopo essere state compilate in una macchina a stati finiti. Quindi un motore regex basato su macchine a stati non può essere usato per ReDoS. Tuttavia, le macchine a stati necessarie possono diventare piuttosto grandi in esempi patologici. Ma limitare la memoria disponibile tende ad essere più facile che limitare il tempo di calcolo disponibile.
Il motore RE2 è stato sviluppato appositamente per gestire regex non attendibili ed è stato progettato per l'esecuzione a tempo lineare.
Un'altra alternativa è assemblare te stesso le regex da una notazione semplificata. Ad esempio, potresti consentire agli utenti di utilizzare modelli glob (come *.txt
). È quindi possibile analizzarlo in un modo che impedisce il backtracking, ad esempio impedendo l'annidamento e utilizzando solo quantificatori avidi. Per molti casi d'uso, una notazione di modello semplificata è completamente sufficiente.
Analizzare un'espressione regolare per vedere se sarà lenta o no, senza che l'analisi diventi lenta , equivale a risolvere il problema di arresto. In altre parole, non è possibile trovare una soluzione corretta e completa.
È possibile, naturalmente, trovare una soluzione che sia corretto e in completa. Ad esempio, è possibile lavorare con una lista bianca restrittiva di funzionalità sicure da usare (ad es. Classi di caratteri sì, ripetizione no ...). Ciò ti consentirebbe di passare molte regex acritiche, rifiutare tutte quelle critiche e (erroneamente) rifiutare alcune che sono a posto, ma troppo complicate per dimostrarsi automaticamente sicure.
Come autore del re parser per il progetto lazzaro, direi che non ci sono modi per capire per una determinata espressione regolare quali risorse consumerà in un dato testo.
Senza spendere le stesse risorse intendo (almeno nel significato di big-O).
Quindi l'approccio migliore: esegui re parser in thread separato e uccidilo dopo il timeout.
Oltre alle altre risposte, una soluzione potrebbe anche essere quella di eseguire il rollup della propria libreria regex, che consente la strumentazione delle prestazioni durante l'esecuzione e quindi fornisce i mezzi per terminare l'esecuzione a metà strada se vengono soddisfatti alcuni criteri.
Allo stesso modo, potresti eseguire le regex su un altro thread e uccidere i thread se impiegano troppo tempo.