fix: reject trailing newline in collection-name validation

Python's $ anchor matches just before a final newline, so a $-anchored
re.match(r'^[a-zA-Z0-9_-]{1,128}$', name) accepted "papers\n". In local
mode get_or_create_collection() then hit SQLite's CHECK via
INSERT OR IGNORE, silently created no row, and returned a Collection that
failed later on add(). Switch all three duplicated validators (local,
cloud, sqlite backends) to re.fullmatch() so the whole string must match.
This commit is contained in:
mountain 2026-07-09 19:12:56 +08:00
parent e00d360273
commit 91e016d2e4
5 changed files with 26 additions and 5 deletions

View file

@ -10,11 +10,13 @@ from ..errors import CollectionAlreadyExistsError, PageIndexError
# itself (not just relying on LocalBackend's pre-check or the schema's CHECK
# constraint below) because it's a public StorageEngine that can be used
# directly, bypassing LocalBackend entirely.
_COLLECTION_NAME_RE = re.compile(r'^[a-zA-Z0-9_-]{1,128}$')
# Matched with .fullmatch() (not .match()): a $-anchored .match() would accept a
# trailing newline ("papers\n") because $ matches just before a final \n.
_COLLECTION_NAME_RE = re.compile(r'[a-zA-Z0-9_-]{1,128}')
def _validate_collection_name(name: str) -> None:
if not _COLLECTION_NAME_RE.match(name):
if not _COLLECTION_NAME_RE.fullmatch(name):
raise PageIndexError(f"Invalid collection name: {name!r}. Must be 1-128 chars of [a-zA-Z0-9_-].")