python / python/cpython

Escaping the `repl` argument to `re.sub()`, `re.subn()`

Ouverte
#128,138 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

docs topic-regex
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Documentation

It's not immediately obvious how to escape the repl (replacement for matches) argument to re.sub() and re.subn() if repl is chosen by a potentially hostile actor. Obviously, re.escape() isn't the answer, as that escapes far too much.

The right answer seems to be escaped_repl = raw_repl.replace(bslash, bslash*2) where bslash = '\\'. It might be worth adding this to the documentation.

Here's the code I used to empirically validate the "right answer" given above (checked on Python 3.8 & 3.12):

from __future__ import annotations
import re, sys

def escape_re_sub_repl(repl: str) -> str:

    return repl.replace('\\', '\\\\')

def test_escape_re_sub_repl() -> None:

    backslash = '\\'
    assert len(backslash) == 1

    base_regex = 'TARGET'
    assert base_regex == re.escape(base_regex)
    base_prefix = 'BEFORE:'
    base_suffix = ':AFTER'
    base_input = f'{base_prefix}{base_regex}{base_suffix}'

    base_chars = tuple(chr(p) for p in range(sys.maxunicode + 1))
    escaped_chars = tuple(f'{backslash}{c}' for c in base_chars)
    test_cases = base_chars + escaped_chars
    assert {len(f) for f in test_cases} == {1, 2}

    for raw in test_cases:
        repl = escape_re_sub_repl(raw)
        got, change_count = re.subn(base_regex, repl, base_input)
        assert change_count == 1
        assert got == f'{base_prefix}{raw}{base_suffix}'

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par localiser la documentation de re.sub() et re.subn(), ainsi que les règles applicables aux chaînes de remplacement. Vérifiez les indications existantes concernant re.escape(), puis documentez l’approche consistant à doubler les barres obliques inverses pour le texte de remplacement hostile et validez-la à l’aide des exemples fournis ; le travail sera considéré comme terminé lorsque les indications relatives à l’échappement sécurisé seront claires dans la documentation concernée.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
documentation
Type d'issue
Documentation
Difficulté
2/5
Temps estimé
1-3 heures
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.