-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
c: use proper type coercion in consume
#44
Conversation
cc @addaleax as well since you are so good at C/C++! |
On 32bit platforms `size_t` is essentially `uint32_t` (or at times even meager `uint16_t`). Loading `uint64_t` field value into `size_t` on these platforms would truncate the high bits and leave only the low 32 (16) bits in place. This leads to various interesting errors in downstream modules. See: - nodejs/llhttp#110 - nodejs/undici#803 This patch makes all field loads go into their respective types. Truncation doesn't happen in this case because C coercion rules will cast both types to the largest necessary datatype to hold either of them.
d09bc9e
to
0ea76ed
Compare
Does it affect 32-bit builds of Node.js too? |
I believe it does. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
+1 for fast-tracking this. |
FWIW, here's how the generated code looks with this patch: size_t avail;
uint64_t need;
avail = endp - p;
need = state->content_length;
if (avail >= need) {
p += need;
state->content_length = 0;
goto s_n_llhttp__internal__n_span_end_llhttp__on_body;
}
state->content_length -= avail;
return s_n_llhttp__internal__n_consume_content_length;
/* UNREACHABLE */;
abort(); Note the |
On 32bit platforms `size_t` is essentially `uint32_t` (or at times even meager `uint16_t`). Loading `uint64_t` field value into `size_t` on these platforms would truncate the high bits and leave only the low 32 (16) bits in place. This leads to various interesting errors in downstream modules. See: - nodejs/llhttp#110 - nodejs/undici#803 This patch makes all field loads go into their respective types. Truncation doesn't happen in this case because C coercion rules will cast both types to the largest necessary datatype to hold either of them. PR-URL: #44 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Daniele Belardi <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Landed in 037dd2f. Thanks y'all! |
I'm still waiting for llhttp's CI run to complete, and will publish patch version releases after that. Will submit PRs to Node.js right after that. We should be able to have a discussion on the release timing there! |
Fix: #37053 See: nodejs/llparse#44 PR-URL: #38665 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Daniele Belardi <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Fix: #37053 See: nodejs/llparse#44 PR-URL: #38665 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Daniele Belardi <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
On 32bit platforms
size_t
is essentiallyuint32_t
(or at timeseven meager
uint16_t
). Loadinguint64_t
field value intosize_t
onthese platforms would truncate the high bits and leave only the low 32
(16) bits in place. This leads to various interesting errors in
downstream modules. See:
This patch makes all field loads go into their respective types.
Truncation doesn't happen in this case because C coercion rules will
cast both types to the largest necessary datatype to hold either of
them.
cc @Trott @mcollina @nodejs/http
I'd appreciate if we could fast-track this. We've been avoiding issues with this for awhile, but both wasm build in unidici and some arm users from the llhttp#110 hit this consistently on large uploads/downloads.