Skip to content

Commit a3394d3

Browse files
committed
Add fuzzer for locale module
Fuzzes the CPython _locale C module (Modules/_localemodule.c) through its two Unicode-consuming entry points. Dispatches per input to either locale.strxfrm() — the locale-aware string-to-transform-key conversion that exercises the underlying wcsxfrm() wrapper and its wchar_t encode/decode boundaries — or locale.strcoll(), which compares two fuzzed Unicode strings via wcscoll() to drive the locale-aware collation path. Inputs are Unicode text drawn from the fuzzed byte stream, so multibyte, surrogate-range, and astral-plane code points all reach the C conversion layer.
1 parent a7e2ec1 commit a3394d3

3 files changed

Lines changed: 42 additions & 1 deletion

File tree

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
all : fuzzer-html fuzzer-email fuzzer-httpclient fuzzer-json fuzzer-difflib fuzzer-csv fuzzer-decode fuzzer-ast fuzzer-tarfile fuzzer-tarfile-hypothesis fuzzer-zipfile fuzzer-zipfile-hypothesis fuzzer-re fuzzer-configparser fuzzer-tomllib fuzzer-plistlib fuzzer-xml fuzzer-zoneinfo fuzzer-binascii
1+
all : fuzzer-html fuzzer-email fuzzer-httpclient fuzzer-json fuzzer-difflib fuzzer-csv fuzzer-decode fuzzer-ast fuzzer-tarfile fuzzer-tarfile-hypothesis fuzzer-zipfile fuzzer-zipfile-hypothesis fuzzer-re fuzzer-configparser fuzzer-tomllib fuzzer-plistlib fuzzer-xml fuzzer-zoneinfo fuzzer-binascii fuzzer-locale
22

33
PYTHON_CONFIG_PATH=$(CPYTHON_INSTALL_PATH)/bin/python3-config
44
CXXFLAGS += $(shell $(PYTHON_CONFIG_PATH) --cflags)
@@ -43,3 +43,6 @@ fuzzer-zoneinfo:
4343

4444
fuzzer-binascii:
4545
clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"binascii.py\"" -ldl $(LDFLAGS) -o fuzzer-binascii
46+
47+
fuzzer-locale:
48+
clang++ $(CXXFLAGS) $(LIB_FUZZING_ENGINE) -std=c++17 fuzzer.cpp -DPYTHON_HARNESS_PATH="\"locale.py\"" -ldl $(LDFLAGS) -o fuzzer-locale

fuzz_targets.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ email email.py
88
html html.py
99
httpclient httpclient.py
1010
json json.py
11+
locale locale.py
1112
plistlib plist.py
1213
re re.py
1314
tarfile tarfile.py

locale.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from fuzzeddataprovider import FuzzedDataProvider
2+
import locale
3+
4+
OP_STRXFRM = 0
5+
OP_STRCOLL = 1
6+
7+
8+
# Fuzzes the _locale C module (Modules/_localemodule.c).
9+
# Exercises locale.strxfrm() for locale-aware string transformation
10+
# and locale.strcoll() for locale-aware string comparison, both with
11+
# fuzz-generated Unicode input.
12+
def FuzzerRunOne(FuzzerInput):
13+
if len(FuzzerInput) < 1 or len(FuzzerInput) > 0x10000:
14+
return
15+
fdp = FuzzedDataProvider(FuzzerInput)
16+
target = fdp.ConsumeIntInRange(OP_STRXFRM, OP_STRCOLL)
17+
n = (
18+
fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 10000))
19+
if fdp.remaining_bytes() > 0
20+
else 0
21+
)
22+
if n == 0:
23+
return
24+
s = fdp.ConsumeUnicode(n)
25+
try:
26+
if target == OP_STRXFRM:
27+
locale.strxfrm(s)
28+
elif target == OP_STRCOLL:
29+
n2 = (
30+
fdp.ConsumeIntInRange(1, min(fdp.remaining_bytes(), 10000))
31+
if fdp.remaining_bytes() > 0
32+
else 0
33+
)
34+
s2 = fdp.ConsumeUnicode(n2) if n2 > 0 else ""
35+
locale.strcoll(s, s2)
36+
except Exception:
37+
pass

0 commit comments

Comments
 (0)