From 11ca5eb3ade66456e11e657f2ff632e642379117 Mon Sep 17 00:00:00 2001 From: Nate Cook Date: Tue, 14 Jul 2026 16:08:37 -0500 Subject: [PATCH] Fix `\w` scalar semantics to match digits and underscore The thorough-check implementation of \w under scalar semantics only checks `isAlphabetic`, which doesn't include digits or an underscore. The quick-match version is correct, so the two don't resolve to the same result, and can produce incorrect matches when the input character is non-ASCII. --- Sources/_StringProcessing/Engine/MEBuiltins.swift | 4 +++- Tests/RegexTests/MatchTests.swift | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Sources/_StringProcessing/Engine/MEBuiltins.swift b/Sources/_StringProcessing/Engine/MEBuiltins.swift index f6d97555d..546721020 100644 --- a/Sources/_StringProcessing/Engine/MEBuiltins.swift +++ b/Sources/_StringProcessing/Engine/MEBuiltins.swift @@ -382,7 +382,9 @@ extension String { } case .word: if isScalarSemantics { - matched = scalar.properties.isAlphabetic && asciiCheck + matched = (scalar.properties.isAlphabetic + || scalar.properties.numericType != nil + || scalar == "_") && asciiCheck } else { matched = char.isWordCharacter && asciiCheck } diff --git a/Tests/RegexTests/MatchTests.swift b/Tests/RegexTests/MatchTests.swift index 2d9a6b1c2..5bf68c106 100644 --- a/Tests/RegexTests/MatchTests.swift +++ b/Tests/RegexTests/MatchTests.swift @@ -952,6 +952,17 @@ extension RegexTests { firstMatchTest( #"(?S)\v"#, input: "\r\n", match: "\r", semanticLevel: .unicodeScalar) + // \w in scalar semantics must match letters, digits, and underscore + // (matching the same definition used in grapheme-cluster semantics), + // not just alphabetics. + matchTest( + #"\w"#, + ("a", true), + ("1", true), + ("_", true), + (" ", false), + semanticLevel: .unicodeScalar) + matchTest( #"[a]\u0301"#, ("a\u{301}", false),