From 0529dca7a263a9ce713dd043d87467d16544e204 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 24 Mar 2026 20:50:05 +0100 Subject: [PATCH] luci-base: fix feature detection patterns Upstream ucode commit 8a8b4d1 ("types: fix regexp `/.../s` flag inversion") changed the semantics of /.../s regexp patterns to match the ECMAScript behavior, meaning `/s` enables single line matching and omitting it performs line-wise matching. Besides changing the behavior of `.` to match newlines, the `/s` flag also changes `^` and `$` to only match the begin and end of the entire string input, respectively instead of matching the start and end of lines. This broke feature pattern matching in the luci rpcd plugin, causing LuCI to incorrectly disable certain features. This commit changes the affected places to read the command outputs linewise and to perform the feature flag matching against each read line individually, including an explicit terminating newline to make the pattern match forward- and backward compatible with fixed and unfixed ucode versions. Fixes: https://github.com/jow-/ucode/issues/389 Signed-off-by: Jo-Philipp Wich --- .../luci-base/root/usr/share/rpcd/ucode/luci | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modules/luci-base/root/usr/share/rpcd/ucode/luci b/modules/luci-base/root/usr/share/rpcd/ucode/luci index 00e2b51474..511853cd71 100644 --- a/modules/luci-base/root/usr/share/rpcd/ucode/luci +++ b/modules/luci-base/root/usr/share/rpcd/ucode/luci @@ -277,13 +277,15 @@ const methods = { let fd = popen('dnsmasq --version 2>/dev/null'); if (fd) { - const m = match(fd.read('all'), /^Compile time options: (.+)$/s); + for (let line = fd.read('line'); length(line); line = fd.read('line')) { + const m = match(line, /^Compile time options: (.+)\n$/); - for (let opt in split(m?.[1], ' ')) { - let f = replace(opt, 'no-', '', 1); + for (let opt in split(m?.[1], ' ')) { + let f = replace(opt, 'no-', '', 1); - result.dnsmasq ??= {}; - result.dnsmasq[lc(f)] = (f == opt); + result.dnsmasq ??= {}; + result.dnsmasq[lc(f)] = (f == opt); + } } fd.close(); @@ -293,11 +295,10 @@ const methods = { fd = popen('odhcpd -h 2>/dev/null'); if (fd) { - const output = fd.read('all'); + for (let line = fd.read('line'); length(line); line = fd.read('line')) { + result.odhcpd ??= {}; - if (output) { - result.odhcpd = {}; - const m = match(output, /^Features: (.+)$/s); + const m = match(line, /^Features: (.+)\n$/); for (let opt in split(m?.[1], ' ')) { let f = replace(opt, 'no-', '', 1);