Coverage for /pythoncovmergedfiles/medio/medio/src/turbohtml/tools/fuzz/idna_nfc_oracles.py: 70%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

37 statements  

1"""Canonical-equivalent labels need an independent target because stable wrong hosts satisfy idempotence.""" 

2 

3from __future__ import annotations 

4 

5import re 

6import unicodedata 

7from typing import TYPE_CHECKING, Final 

8 

9from turbohtml.extract import normalize_url 

10 

11if TYPE_CHECKING: 

12 import random 

13 from collections.abc import Callable 

14 

15 

16def idna_nfc_check(case: str, normalize: Callable[[str], str] = normalize_url) -> str | None: 

17 """Pin equivalent spellings to an independent target instead of trusting their agreement.""" 

18 variant, separator, affix = case.partition(":") 

19 if not separator or variant not in _LABELS or re.fullmatch(r"[a-z0-9]{0,8}", affix) is None: 

20 raise UnsupportedIdnaNfcCaseError(case) 

21 source: Final = affix + _LABELS[variant] 

22 composed: Final = unicodedata.normalize("NFC", source) 

23 expected: Final = f"https://xn--{composed.encode('punycode').decode('ascii')}.example/" 

24 for label in (source, composed, unicodedata.normalize("NFD", source)): 

25 try: 

26 output = normalize(f"https://{label}.example/") 

27 except ValueError: 

28 return "rejects known-valid canonical host" 

29 if output != expected: 

30 return "canonical host differs from independent target" 

31 try: 

32 repeated: Final = normalize(expected) 

33 except ValueError: 

34 return "rejects canonical host output" 

35 return None if repeated == expected else "canonical host changes on repeat" 

36 

37 

38def idna_nfc_generate(rng: random.Random) -> str: 

39 """Limit labels to established Unicode-16 mappings without unrelated IDNA policies.""" 

40 return f"{rng.choice(tuple(_LABELS))}:g{rng.randrange(10000)}" 

41 

42 

43def idna_nfc_seeds() -> list[str]: 

44 """Exercise composition and ordering families before random generation.""" 

45 return [f"{variant}:g{index}" for variant in _LABELS for index in range(20)] 

46 

47 

48def idna_nfc_controls() -> dict[str, bool]: 

49 """Reject stable wrong results as well as unstable canonical output.""" 

50 return { 

51 "unchanged Unicode": idna_nfc_check("reorder:", lambda text: text) is not None, 

52 "stable wrong target": idna_nfc_check("reorder:", lambda _text: "https://wrong.example/") is not None, 

53 "changed repeat": idna_nfc_check("reorder:", lambda text: text + "x" if text.isascii() else normalize_url(text)) 

54 is not None, 

55 } 

56 

57 

58class UnsupportedIdnaNfcCaseError(ValueError): 

59 """Keep unsupported fixture grammar distinct from rejection of valid hosts.""" 

60 

61 

62_LABELS: Final[dict[str, str]] = { 

63 "reorder": "q\u0301\u0323", 

64 "blocked": "a\u0305\u0301", 

65 "successive-compose": "a\u030a\u0301", 

66 "noncomposing-tail": "s\u0323\u0301", 

67 "lower-class-intervening": "a\u0316\u0301", 

68 "hangul-lv": "\u1100\u1161", 

69 "hangul-lvt": "\u1100\u1161\u11a8", 

70 "hangul-lv-plus-t": "\uac00\u11a8", 

71} 

72 

73__all__ = [ 

74 "UnsupportedIdnaNfcCaseError", 

75 "idna_nfc_check", 

76 "idna_nfc_controls", 

77 "idna_nfc_generate", 

78 "idna_nfc_seeds", 

79]