On Mon, Mar 2, 2026 at 08:58 PM, Khem Raj wrote:

> 
> 
> 
> On Mon, Mar 2, 2026 at 7:15 AM Jeevan via lists.openembedded.org (
> http://lists.openembedded.org ) <j-sahu= [email protected] >
> wrote:
> 
>> On Mon, Mar 2, 2026 at 08:27 PM, Khem Raj wrote:
>> 
>>> 
>>> 
>>> On Mon, Mar 2, 2026 at 6:47 AM Jeevan via lists.openembedded.org (
>>> http://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 ( http://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.
>>> 
>>> 
>>> 
>> 
>> This patch manually applies the logic to the generated C code. Upstream
>> (llparse/llhttp/nodejs)
>> would never accept patches to generated files - they'd regenerate or
>> update the bundled version.
>> That's why I used "Inappropriate" per Yocto guidelines.
>> 
> 
> 
> I see, we do not regenerate the file ? if that something lacking in the
> build process in OE for this package then
> 
> 

llparse is a Node.js tool that generates the HTTP parser. Node.js upstream 
ships this pre-generated (common for complex generators),
and most distros (Debian, Fedora, Arch) use it as-is. The nodejs recipe in 
meta-oe follows the same approach - I believe this is a
deliberate trade-off rather than a gap.

> 
> 
>> 
>> 
>>> 
>>> 
>>>> +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 (
>>>> http://nodejs_22.22.0.bb ) b/meta-oe/recipes-devtools/nodejs/ 
>>>> nodejs_22.22.0.bb
>>>> ( http://nodejs_22.22.0.bb )
>>>> index 05fa608047..d08c5d8318 100644
>>>> --- a/meta-oe/recipes-devtools/nodejs/ nodejs_22.22.0.bb (
>>>> http://nodejs_22.22.0.bb )
>>>> +++ b/meta-oe/recipes-devtools/nodejs/ nodejs_22.22.0.bb (
>>>> http://nodejs_22.22.0.bb )
>>>> @@ -33,6 +33,7 @@ SRC_URI = " 
>>>> https://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz
>>>> ( https://nodejs.org/dist/v$%7BPV%7D/node-v$%7BPV%7D.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 (#124817): 
https://lists.openembedded.org/g/openembedded-devel/message/124817
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]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to