Tornar al Blog

Rendiment i validació amb regex: evita patrons ambigus

UtilX Publicat el 4/9/2026 Actualitzat el 4/9/2026 11 min lectura

Comparació del creixement del backtracking en una expressió acotada i una de niada

Les expressions regulars són útils per comprovar una forma local: un prefix, uns separadors o una longitud. No proven que una dada sigui correcta, segura o barata de processar. Un patró pot acceptar una cadena inadequada i un altre, aparentment senzill, pot trigar massa quan una entrada gairebé coincideix. Aquesta guia treballa amb mostres sintètiques per revisar rendiment i validació sense convertir una expressió lenta en una recepta d'atac.

El problema

El risc apareix quan diverses parts de l'expressió poden consumir el mateix text i el motor prova moltes reparticions abans de fallar. Els quantificadors niats, les alternatives que se solapen i els finals ambigus en són avisos habituals. En un motor amb backtracking, una entrada llarga gairebé vàlida pot obligar a tornar enrere repetidament. Això pot congelar una interfície, consumir CPU o deixar un servei sense resposta. OWASP anomena aquesta família ReDoS quan una altra persona pot controlar l'entrada.

No tota regex amb parèntesis o asteriscs és perillosa. El cost depèn del motor, de l'expressió completa, dels límits d'entrada i de la manera d'invocar-la. Tanmateix, esperar un incident és un mal disseny. Un camp ha d'explicar quin format necessita, quina mida màxima admet i què passa si el valor no encaixa. Si la regla representa una identitat, una decisió de negoci o una quantitat, necessita comprovacions semàntiques fora de la regex.

/regex-tester pot servir per inspeccionar coincidències amb mostres no sensibles. No demostra que una regla sigui segura per a qualsevol longitud ni substitueix les defenses del sistema que rep la dada. Anota el motor, les banderes i els límits: la sintaxi i el comportament no són iguals a tots els llenguatges. L'especificació ECMAScript descriu les expressions de JavaScript, però un servidor pot emprar una biblioteca diferent.

Exemple pràctic

Considera l'expressió de demostració ^(a+)+$. El problema és que el grup repetit conté un altre quantificador i pot dividir una seqüència de lletres a de moltes maneres. Estudia-la només amb un valor curt que ha de coincidir, com aaaa, i amb un valor gairebé vàlid que acaba en un altre caràcter, com aaaa!. No n'augmentis la mida agressivament ni executis la mostra sobre peticions reals. L'objectiu és reconèixer l'ambigüitat, no mesurar el dany possible.

Per al requisit inventat «d'una a seixanta lletres a», una alternativa acotada és ^a{1,60}$. Explicita el màxim i deixa una única manera rellevant de revisar cada caràcter. aaaa és vàlid; aaaa!, una cadena buida i 61 lletres són invàlids. El seixanta no és una recomanació general: només pertany a aquest camp fictici. Un identificador real necessita alfabets, normalització i longitud decidits pel seu contracte.

El contrast mostra que sintaxi curta no significa semàntica clara. La versió acotada exposa el màxim a qui la revisa. I un resultat booleà no explica per què un valor és acceptable. Una regex pot exigir vuit caràcters alfanumèrics, però no pot provar que un compte existeixi, que dues dates formin un interval coherent o que un import estigui autoritzat. Aquestes preguntes requereixen dades i regles addicionals.

Procediment

Descriu el valor en llenguatge normal abans d'escriure la regex. Indica si s'admet buit, Unicode, espais inicials o finals, separadors i cada límit de longitud. Decideix també on es normalitza; retallar espais, canviar majúscules o normalitzar Unicode després de validar pot canviar el significat. Si no pots explicar la regla sense ensenyar l'expressió, probablement barreges format i política de negoci.

Crea una taula petita de mostres representatives: un valor vàlid ordinari, mínim, màxim, caràcters semblants però prohibits, buit i massa llarg. Conserva-les sintètiques. Executa-les al motor real de l'aplicació i registra coincidència, durada aproximada i grups capturats quan calgui. Les proves de regressió han de comprovar resultats, no un nombre exacte de mil·lisegons que varia entre equips.

Revisa l'estructura abans d'optimitzar. Cerca repeticions dins de repeticions, alternatives on una opció és prefix d'una altra i comodins sense límit abans d'un delimitador incert. Pregunta't si un quantificador pot ser un interval finit, un separador pot ser explícit o l'anàlisi es pot dividir en passos. Evita copiar patrons amplis d'internet per a camps estrets: sovint admeten molt més del que el producte necessita.

Aplica defenses al voltant de la regex. Rebutja dades massa llargues abans d'avaluar-les, limita el cos de la petició i fixa un pressupost de temps si la plataforma ho permet. En un navegador, no executis una regla costosa a cada pulsació sense un màxim; limita longitud i ajorna treball quan convingui. El servei necessita els mateixos límits encara que el client ja hagi validat, perquè una petició pot evitar la interfície.

Explicació tècnica

Un motor de backtracking tria una ruta i, si el final no encaixa, torna a una decisió anterior per provar-ne una altra. Amb ^(a+)+$, cada grup interior pot prendre una quantitat diferent de a; en arribar a !, explora combinacions que acaben fallant. La visual adjunta no ofereix temps universals: explica per què una ruta ambigua creix molt més de pressa que una comprovació fixa. Alguns motors optimitzen casos concrets, però una política de seguretat no s'ha de basar en una optimització no garantida.

Els ancoratges ^ i $ expressen la intenció de validar tot el text, però importen les opcions multilínia i l'API. Buscar una subcadena no és igual que exigir coincidència completa. També importa si un objecte regex té estat i si la dada es transforma abans de comparar-la. Llegeix la documentació del llenguatge i prova el codi d'integració, no només un patró enganxat en una web.

Les regex funcionen millor amb gramàtiques regulars petites: prefixos permesos, separadors, caràcters i límits. La validació semàntica ve després: converteix un número i comprova rang; interpreta una data i verifica calendari; consulta valors admesos; compara permisos al servidor. Separar fases dona errors útils i evita una expressió gegant que ningú no pot revisar amb confiança.

Errors freqüents

Un error freqüent és tractar un patró copiat per a correus, URL o contrasenyes com si fos una especificació completa. Molts formats tenen excepcions, internacionalització o regles canviants. Una regex massa estricta rebutja persones legítimes; una de massa ampla desplaça el treball difícil. Defineix la política del producte i els seus límits en lloc d'afirmar que una sola expressió implementa tot un estàndard extern.

També falla provar només entrades felices. Una regla pot coincidir amb deu exemples normals i degradar-se amb un valor llarg que falla al darrer caràcter. Afegeix casos de frontera i prova'ls localment en el context real. No publiquis ni automatitzis càrregues creixents contra sistemes que no controles. Detecta l'ambigüitat en una còpia local i substitueix-la per una regla acotada.

La validació del navegador no és una frontera de seguretat. Ajuda la persona usuària, però una petició es pot construir sense interfície. El servidor ha de tornar a comprovar format, longitud, permisos i negoci. La codificació de sortida continua sent necessària: haver coincidit amb una regex no fa segura una dada per a HTML, SQL, una ruta o una ordre del sistema.

Consideracions

Prefereix límits que surtin del domini: 64 caràcters perquè el camp ho defineix, quatre segments perquè el protocol ho exigeix o una llista finita mantinguda. Mesura l'entrada abans de convertir-la o desar-la. Si la dada és gran per disseny, usa un analitzador adequat o processa per parts; no intentis descriure un document sencer amb una regex d'una línia.

Documenta motor i banderes amb la regla. En JavaScript, el mode Unicode, les majúscules i les classes de caràcters canvien el resultat. Revisa versions de dependències si el patró arriba a un component extern. En regles rellevants per a seguretat, una altra persona ha de poder llegir intenció, mostres i límits sense memoritzar cada metacaràcter.

Observa errors i latència sense guardar valors sensibles complets. Comptadors de rebuigs per mida o format poden revelar que una regla necessita una explicació millor. Si el temps és anòmal, conserva mostres artificials que en reprodueixin la forma i minimitza el cas abans de corregir-lo. L'observació ajuda a prioritzar; no substitueix el límit preventiu.

Limitacions

Aquesta guia no certifica que una regex concreta no tingui ReDoS ni ofereix un temps d'espera vàlid per a tots els navegadors, servidors i motors. El rendiment depèn d'implementació, maquinari, concurrència i entrada. L'exemple niat és només per a revisió controlada; no s'ha de desplegar com a validador ni usar per provar serveis de tercers.

Una expressió acotada tampoc resol autenticació, autorització, normalització d'identitat, injecció o privacitat. Cada context de sortida necessita codificació adequada i cada decisió sensible necessita controls de confiança. Consulta la documentació del motor i les guies de seguretat aplicables abans d'usar un patró en una frontera exposada.

Llista de comprovació

Descriu la dada i els límits abans d'escriure la regex. Prova mostres vàlides, invàlides, buides i massa llargues al motor real. Evita quantificadors niats i alternatives competidores; prefereix classes explícites i intervals finits. Limita mida abans d'avaluar i valida de nou al servidor. Separa format i semàntica, registra intenció i banderes, observa fallades sense retenir secrets i revisa qualsevol patró d'una ruta pública.