From 652ddf866f371acd5fee2ada055e01a473f78ea8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 16 Apr 2021 12:34:29 +0200 Subject: [PATCH] ucm: allow to escape the trailing variable substitution character Example: ${find-device:ctl='hw:0',type=pcm,field=id,regex='USB A{1\\}'} Unescaped find-device arguments: ctl='hw:0',type=pcm,field=id,regex='USB A{1}' Signed-off-by: Jaroslav Kysela --- src/ucm/ucm_subs.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/ucm/ucm_subs.c b/src/ucm/ucm_subs.c index c9023460..b9fee72e 100644 --- a/src/ucm/ucm_subs.c +++ b/src/ucm/ucm_subs.c @@ -594,13 +594,52 @@ static char *rval_var(snd_use_case_mgr_t *uc_mgr, const char *id) goto __match2; \ } +/* + * skip escaped } character (simple version) + */ +static inline const char *strchr_with_escape(const char *str, char c) +{ + char *s; + + while (1) { + s = strchr(str, c); + if (s && s != str) { + if (*(s - 1) == '\\') { + str = s + 1; + continue; + } + } + return s; + } +} + +/* + * remove escaped } character (simple version) + */ +static inline void strncpy_with_escape(char *dst, const char *src, size_t len) +{ + char c; + + c = *src++; + while (c != '\0' && len > 0) { + if (c == '\\' && *src == '}') { + c = *src++; + len--; + } + *dst++ = c; + len--; + c = *src++; + } + *dst = '\0'; +} + int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr, char **_rvalue, const char *value) { size_t size, nsize, idsize, rvalsize, dpos = 0; const char *tmp; - char *r, *nr, *rval, v2[48]; + char *r, *nr, *rval, v2[128]; bool ignore_error, allow_empty; char *(*fcn2)(snd_use_case_mgr_t *, const char *id); int err; @@ -658,15 +697,14 @@ __merr: } goto __error; __match2: - tmp = strchr(value + idsize, '}'); + tmp = strchr_with_escape(value + idsize, '}'); if (tmp) { rvalsize = tmp - (value + idsize); if (rvalsize >= sizeof(v2)) { err = -ENOMEM; goto __error; } - strncpy(v2, value + idsize, rvalsize); - v2[rvalsize] = '\0'; + strncpy_with_escape(v2, value + idsize, rvalsize); idsize += rvalsize + 1; if (*v2 == '$' && uc_mgr->conf_format >= 3) { tmp = uc_mgr_get_variable(uc_mgr, v2 + 1); -- 2.47.1