fix: reject string schemas that mix pattern/format with length bounds (#49996)

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
This commit is contained in:
Yufeng He
2026-08-19 17:29:32 +08:00
committed by GitHub
parent 93eea4f665
commit 340b7e4909
2 changed files with 20 additions and 0 deletions
+6
View File
@@ -14,6 +14,12 @@ pytestmark = pytest.mark.cpu_test
def unsupported_string_schemas():
return [
{"type": "string", "format": "non_existing_format"},
# pattern/format is compiled but length bounds are silently dropped,
# so the combination must be rejected instead of producing quietly
# wrong output
{"type": "string", "pattern": "^a+$", "maxLength": 2},
{"type": "string", "pattern": "^a+$", "minLength": 3},
{"type": "string", "format": "email", "maxLength": 10},
]
@@ -262,6 +262,20 @@ def has_xgrammar_unsupported_json_features(schema: dict[str, Any]) -> bool:
):
return True
# A string mixing a generative constraint (pattern or format) with
# explicit length bounds. xgrammar compiles the pattern/format side
# and silently drops minLength/maxLength from the grammar, so output
# can violate the bound without any error surfacing. Verified against
# the compiled EBNF: pattern/format grammars come out byte-identical
# with and without the length keywords, while maxLength alone lowers
# to {0, N} correctly.
if (
obj.get("type") == "string"
and ("pattern" in obj or "format" in obj)
and ("minLength" in obj or "maxLength" in obj)
):
return True
# Unsupported keywords for objects
if obj.get("type") == "object" and any(
key in obj for key in ("patternProperties", "propertyNames")