From b6a5283331f1deef5bccd3e91520bdd9acd8568d Mon Sep 17 00:00:00 2001 From: Jiri Kyjovsky Date: Wed, 6 May 2026 23:06:01 +0200 Subject: [PATCH] init: fix unescape_string not advancing past escape characters After processing a \X escape sequence in the switch block, the read pointer (val) was not advanced past the matched character. The next loop iteration re-processed it as a literal, producing an extra byte for every escape sequence. For example, JSON "\n" decoded to {0x0A, 'n'} instead of {0x0A}, and JSON "\\\\" decoded to {'\', } instead of {'\'}. Also fix the \u case: hexToDigit was called with a pointer to 'u' instead of the first hex digit (val++ vs ++val), and the write index was not advanced after memcpy, so decoded Unicode characters were silently dropped. This caused e.g. \u0026 ('&') to be lost, breaking any container command containing '&&'. --- init/init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/init/init.c b/init/init.c index 3b20d2fcb..38d464d9d 100644 --- a/init/init.c +++ b/init/init.c @@ -666,7 +666,8 @@ static void unescape_string(char *string, int len) const char *unescaped = "?"; char utf8Buf[5]; unsigned int codepoint = 0; - hexToDigit(&codepoint, val++); + /* skip 'u', point at first hex digit */ + hexToDigit(&codepoint, ++val); val += 3; /* check if this is a surrogate */ if ((codepoint & 0xFC00) == 0xD800) { @@ -692,9 +693,11 @@ static void unescape_string(char *string, int len) continue; } memcpy(&string[i], unescaped, (unsigned int)strlen(unescaped)); + i += strlen(unescaped); break; } } + val++; } string[i] = '\0'; }