]> git.alsa-project.org Git - alsa-ucm-conf.git/commitdiff
ucm2: use locale-agnostic character classes in parsing regexes HEAD master
authorJaroslav Kysela <perex@perex.cz>
Mon, 14 Sep 2026 16:34:49 +0000 (18:34 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 14 Sep 2026 16:35:08 +0000 (18:35 +0200)
Several UCM configuration regexes parse CardComponents using POSIX
bracket *ranges* such as "[a-z0-9]", "[a-z0-9-]" and "[0-9a-f]".
Range expressions are locale sensitive: the set of characters covered
by "x-y" depends on the current collation order (LC_COLLATE), not on
code points.

Under the Turkish locale (tr_TR.UTF-8) the dotless/dotted 'i' handling
reorders the collation sequence, so "[a-z]" no longer matches every
lowercase ASCII letter.  As a result the "mic:...-dmic" component in
sof-soundwire.conf is truncated (e.g. to "dm"), ALSA then tries to open
a non-existent "dm.conf" and the whole UCM import for the SoundWire card
aborts, leaving the user with a dummy-only audio profile (no speaker,
no microphone).

Fix the whole tree by switching to POSIX character classes, which are
defined by character classification instead of collation order and thus
match the intended ASCII set regardless of the active locale:

  - sof-soundwire.conf: "[a-z0-9]" -> "[[:alnum:]]",
                        "[a-z0-9-]" -> "[[:alnum:]-]"
  - USB-Audio.conf:     "[0-9a-f]" -> "[[:xdigit:]]"

[[:xdigit:]] is used for the USB vendor/device IDs because it matches
exactly the hexadecimal digits (and, unlike [[:digit:]], stays
restricted to ASCII in glibc).  Pure digit ranges such as "[0-9]" are
left untouched: digits do not collation-reorder and the range already
matches only ASCII digits.

Fixes: https://github.com/alsa-project/alsa-ucm-conf/issues/824
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
ucm2/USB-Audio/USB-Audio.conf
ucm2/sof-soundwire/sof-soundwire.conf

index ea35792a608021ddbe71bd0b13a44fa15489ca12..476e679c547be3b865c35c4810ca83d36820f6cc 100644 (file)
@@ -8,7 +8,7 @@ Define.ProfileName ""
 Define.MixerRemap ""
 Define.SplitPCMPeriodTime 10000                # 10ms
 DefineRegex.USBID {
-       Regex "USB([0-9a-f]{4}):([0-9a-f]{4})"
+       Regex "USB([[:xdigit:]]{4}):([[:xdigit:]]{4})"
        String "${CardComponents}"
 }
 
index 95bd28b8d737687a93a385c107cc455ed7d67e82..d6cb2489ea66931adcb2c7f4c5beaed41778847a 100644 (file)
@@ -24,7 +24,7 @@ Define {
 
 DefineRegex {
        SpeakerCodec {
-               Regex " spk:([a-z0-9]+((-sdca)|(-spk)|(-bridge))?(\\+[a-z0-9]+((-spk)?))?)"
+               Regex " spk:([[:alnum:]]+((-sdca)|(-spk)|(-bridge))?(\\+[[:alnum:]]+((-spk)?))?)"
                String "${CardComponents}"
        }
        SpeakerChannels {
@@ -36,11 +36,11 @@ DefineRegex {
                String "${CardComponents}"
        }
        HeadsetCodec {
-               Regex " hs:([a-z0-9]+(-sdca)?)"
+               Regex " hs:([[:alnum:]]+(-sdca)?)"
                String "${CardComponents}"
        }
        MicCodec {
-               Regex " mic:([a-z0-9]+(-dmic)?+(-sdca)?)"
+               Regex " mic:([[:alnum:]]+(-dmic)?+(-sdca)?)"
                String "${CardComponents}"
        }
        Mics {
@@ -69,7 +69,7 @@ If.old_multi_spk {
 
 # for speaker, do codec+amplifier split
 If.spk_amp_split1.Append.DefineRegex.SpeakerSplit {
-       Regex "([a-z0-9-]+)\\+([a-z0-9-]+)"
+       Regex "([[:alnum:]-]+)\\+([[:alnum:]-]+)"
        String "${var:SpeakerCodec1}"
 }
 If.spk_amp_split2 {