On Mon, Mar 2, 2026 at 6:47 AM Jeevan via lists.openembedded.org <j-sahu= [email protected]> wrote:
> The NEON SIMD fast path in the bundled llhttp calls > __builtin_ctzll(match_mask) without checking if match_mask is zero. > When all 16 bytes in a NEON register are valid header value characters, > match_mask is 0. Calling __builtin_ctzll(0) is undefined behavior. > > GCC at -O2 exploits this by optimizing "if (match_len != 16)" to > always-true, causing HTTP 400 Bad Request for any header value longer > than 16 characters on ARM targets with NEON enabled. > > Fix by explicitly checking for match_mask == 0 and setting > match_len = 16. This bug affects both aarch64 and armv7 NEON targets. > > The code this patch modifies is generated, so the patch itself isn't > suitable for upstream submission, as the root cause of the error is > in the generator itself. The fix has been merged upstream[1] in > llparse 7.3.1 and is included in llhttp 9.3.1. This patch can be > dropped when nodejs updates its bundled llhttp to >= 9.3.1. > > [1]: https://github.com/nodejs/llparse/pull/83 > > Signed-off-by: Telukula Jeevan Kumar Sahu <[email protected]> > --- > ...header-value-__builtin_ctzll-undefin.patch | 60 +++++++++++++++++++ > .../recipes-devtools/nodejs/nodejs_22.22.0.bb | 1 + > 2 files changed, 61 insertions(+) > create mode 100644 > meta-oe/recipes-devtools/nodejs/nodejs/0001-llhttp-fix-NEON-header-value-__builtin_ctzll-undefin.patch > > diff --git > a/meta-oe/recipes-devtools/nodejs/nodejs/0001-llhttp-fix-NEON-header-value-__builtin_ctzll-undefin.patch > b/meta-oe/recipes-devtools/nodejs/nodejs/0001-llhttp-fix-NEON-header-value-__builtin_ctzll-undefin.patch > new file mode 100644 > index 0000000000..683dddcf04 > --- /dev/null > +++ > b/meta-oe/recipes-devtools/nodejs/nodejs/0001-llhttp-fix-NEON-header-value-__builtin_ctzll-undefin.patch > @@ -0,0 +1,60 @@ > +From a63a5faea54055973bf5f0a514444532563cc20d Mon Sep 17 00:00:00 2001 > +From: Telukula Jeevan Kumar Sahu <[email protected]> > +Date: Fri, 27 Feb 2026 20:58:43 +0530 > +Subject: [PATCH] llhttp: fix NEON header value __builtin_ctzll undefined > + behavior > + > +When all 16 bytes match the allowed range, match_mask becomes 0 after > +the bitwise NOT. Calling __builtin_ctzll(0) is undefined behavior per > +the C standard. > + > +The code expects match_len == 16 when all bytes match (so the branch > +is skipped and p += 16 continues the loop), but this relied on > +ctzll(0) returning 64, which is not guaranteed. > + > +GCC at -O2 exploits this UB by deducing that __builtin_ctzll() result > +is always in range [0, 63], and after >> 2 always in [0, 15], which > +is never equal to 16. The compiler then optimizes > +"if (match_len != 16)" to always-true, causing every valid 16-byte > +chunk to be falsely rejected as containing an invalid character. > + > +This manifests as HTTP 400 Bad Request (HPE_INVALID_HEADER_TOKEN) for > +any HTTP header value longer than 16 characters on ARM targets with > +NEON enabled. > + > +Fix by explicitly checking for match_mask == 0 and setting > +match_len = 16, avoiding the undefined behavior entirely. This bug > +affects both aarch64 and armv7 NEON targets. > + > +The fix has been merged upstream in llparse 7.3.1 [1] and is included > +in llhttp 9.3.1. This patch can be dropped when nodejs updates its > +bundled llhttp to >= 9.3.1. > + > +[1]: https://github.com/nodejs/llparse/pull/83 > + > +Upstream-Status: Inappropriate > If this fix is merged upstream then status should be 'Backport' with appropriate links to point to upstream fix. > +Signed-off-by: Telukula Jeevan Kumar Sahu <[email protected]> > +--- > + deps/llhttp/src/llhttp.c | 6 +++++- > + 1 file changed, 5 insertions(+), 1 deletion(-) > + > +diff --git a/deps/llhttp/src/llhttp.c b/deps/llhttp/src/llhttp.c > +index 14b731e..b0a46c6 100644 > +--- a/deps/llhttp/src/llhttp.c > ++++ b/deps/llhttp/src/llhttp.c > +@@ -2651,7 +2651,11 @@ static llparse_state_t llhttp__internal__run( > + mask = vorrq_u8(mask, single); > + narrow = vshrn_n_u16(vreinterpretq_u16_u8(mask), 4); > + match_mask = ~vget_lane_u64(vreinterpret_u64_u8(narrow), 0); > +- match_len = __builtin_ctzll(match_mask) >> 2; > ++ if (match_mask == 0) { > ++ match_len = 16; > ++ } else { > ++ match_len = __builtin_ctzll(match_mask) >> 2; > ++ } > + if (match_len != 16) { > + p += match_len; > + goto s_n_llhttp__internal__n_header_value_otherwise; > +-- > +2.34.1 > + > diff --git a/meta-oe/recipes-devtools/nodejs/nodejs_22.22.0.bb > b/meta-oe/recipes-devtools/nodejs/nodejs_22.22.0.bb > index 05fa608047..d08c5d8318 100644 > --- a/meta-oe/recipes-devtools/nodejs/nodejs_22.22.0.bb > +++ b/meta-oe/recipes-devtools/nodejs/nodejs_22.22.0.bb > @@ -33,6 +33,7 @@ SRC_URI = " > https://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \ > file://0001-build-remove-redundant-mXX-flags-for-V8.patch \ > file://0001-fix-arm-Neon-intrinsics-types.patch \ > file://0001-detect-aarch64-Neon-correctly.patch \ > + > file://0001-llhttp-fix-NEON-header-value-__builtin_ctzll-undefin.patch \ > file://run-ptest \ > " > SRC_URI:append:class-target = " \ > -- > 2.34.1 > > > > >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#124810): https://lists.openembedded.org/g/openembedded-devel/message/124810 Mute This Topic: https://lists.openembedded.org/mt/118094533/21656 Group Owner: [email protected] Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
