Skip to content

fix: check push id before decoding a blocked push promise#3819

Open
uwezkhan wants to merge 1 commit into
mozilla:mainfrom
uwezkhan:push-id-before-decode
Open

fix: check push id before decoding a blocked push promise#3819
uwezkhan wants to merge 1 commit into
mozilla:mainfrom
uwezkhan:push-id-before-decode

Conversation

@uwezkhan

Copy link
Copy Markdown
Contributor

handle_push_promise checks the Push ID only through new_push_promise, which runs after the QPACK header block decodes. Before this change, a header block that refers to a dynamic table entry the server has not delivered yet blocks the decoder, so the frame lands on blocked_push_promise with no check, and a server that keeps the decoder blocked can push any Push ID unvalidated. RFC 9114 Section 7.2.5 wants a Push ID above the maximum treated as H3_ID_ERROR.

After, check_push_id runs at the top of handle_push_promise, before any decode or buffering, so the error is raised as soon as the frame arrives whatever the decoder state. The check stays in the push controller since that is where the maximum lives; the tradeoff is that a valid Push ID is now checked twice, once here and again in new_push_promise after unblocking. In-range Push IDs behave as before.

@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.80%. Comparing base (9ec0cc6) to head (1335a8e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3819      +/-   ##
==========================================
- Coverage   96.93%   96.80%   -0.13%     
==========================================
  Files         115      120       +5     
  Lines       40516    40873     +357     
  Branches    40516    40873     +357     
==========================================
+ Hits        39275    39568     +293     
- Misses       1226     1280      +54     
- Partials       15       25      +10     
Flag Coverage Δ
freebsd 94.14% <100.00%> (-0.14%) ⬇️
linux 96.98% <100.00%> (+0.02%) ⬆️
macos 95.08% <100.00%> (-0.01%) ⬇️
windows 95.13% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
neqo-common 99.23% <ø> (ø)
neqo-http3 95.41% <100.00%> (+<0.01%) ⬆️
neqo-qpack 97.26% <ø> (ø)
neqo-transport 97.76% <ø> (+0.04%) ⬆️
neqo-udp 95.37% <ø> (ø)
mtu 89.13% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented Jul 18, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 7.59%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
✅ 80 untouched benchmarks

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation simulated/10-streams/each-1048576-bytes 246.9 ms 229.5 ms +7.59%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing uwezkhan:push-id-before-decode (1335a8e) with main (9ec0cc6)

Open in CodSpeed

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark results

No significant performance differences relative to 9ec0cc6.

All results
streams/walltime/1-streams/each-1000-bytes: No change in performance detected.
       time:   [543.12 µs 544.91 µs 546.98 µs]
       thrpt:  [1.7435 MiB/s 1.7502 MiB/s 1.7559 MiB/s]
change:
       time:   [-0.5025% -0.0263% +0.3900] (p = 0.91 > 0.05)
       thrpt:  [-0.3885% +0.0263% +0.5051]
       No change in performance detected.
Found 11 outliers among 100 measurements (11.00%)
3 (3.00%) high mild
8 (8.00%) high severe
streams/walltime/1000-streams/each-1-bytes: Change within noise threshold.
       time:   [11.004 ms 11.020 ms 11.036 ms]
       thrpt:  [88.488 KiB/s 88.621 KiB/s 88.749 KiB/s]
change:
       time:   [-0.7451% -0.5283% -0.3083] (p = 0.00 < 0.05)
       thrpt:  [+0.3093% +0.5311% +0.7507]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
streams/walltime/1000-streams/each-1000-bytes: Change within noise threshold.
       time:   [32.064 ms 32.103 ms 32.143 ms]
       thrpt:  [29.670 MiB/s 29.707 MiB/s 29.743 MiB/s]
change:
       time:   [-0.8171% -0.6291% -0.4509] (p = 0.00 < 0.05)
       thrpt:  [+0.4530% +0.6331% +0.8238]
       Change within noise threshold.
streams-flow-controlled/walltime/1-streams/each-4194304-bytes: Change within noise threshold.
       time:   [27.380 ms 27.416 ms 27.452 ms]
       thrpt:  [145.71 MiB/s 145.90 MiB/s 146.09 MiB/s]
change:
       time:   [+0.1592% +0.3507% +0.5536] (p = 0.00 < 0.05)
       thrpt:  [-0.5505% -0.3494% -0.1589]
       Change within noise threshold.
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) low mild
1 (1.00%) high mild
streams-flow-controlled/walltime/10-streams/each-1048576-bytes: No change in performance detected.
       time:   [71.890 ms 72.369 ms 72.870 ms]
       thrpt:  [137.23 MiB/s 138.18 MiB/s 139.10 MiB/s]
change:
       time:   [-0.4964% +0.4042% +1.3214] (p = 0.39 > 0.05)
       thrpt:  [-1.3042% -0.4026% +0.4989]
       No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/walltime/pacing-false/varying-seeds: Change within noise threshold.
       time:   [18.288 ms 18.300 ms 18.311 ms]
       thrpt:  [218.45 MiB/s 218.58 MiB/s 218.72 MiB/s]
change:
       time:   [-1.4481% -1.2339% -1.0918] (p = 0.00 < 0.05)
       thrpt:  [+1.1039% +1.2493% +1.4694]
       Change within noise threshold.
transfer/walltime/pacing-true/varying-seeds: Change within noise threshold.
       time:   [18.606 ms 18.617 ms 18.628 ms]
       thrpt:  [214.73 MiB/s 214.86 MiB/s 214.99 MiB/s]
change:
       time:   [-3.0109% -2.7852% -2.6235] (p = 0.00 < 0.05)
       thrpt:  [+2.6942% +2.8650% +3.1044]
       Change within noise threshold.
Found 17 outliers among 100 measurements (17.00%)
1 (1.00%) low severe
6 (6.00%) low mild
7 (7.00%) high mild
3 (3.00%) high severe
transfer/walltime/pacing-false/same-seed: Change within noise threshold.
       time:   [18.193 ms 18.204 ms 18.215 ms]
       thrpt:  [219.60 MiB/s 219.73 MiB/s 219.86 MiB/s]
change:
       time:   [-1.4306% -1.3461% -1.2597] (p = 0.00 < 0.05)
       thrpt:  [+1.2758% +1.3645% +1.4513]
       Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
1 (1.00%) low mild
1 (1.00%) high mild
1 (1.00%) high severe
transfer/walltime/pacing-true/same-seed: Change within noise threshold.
       time:   [18.735 ms 18.745 ms 18.755 ms]
       thrpt:  [213.27 MiB/s 213.39 MiB/s 213.50 MiB/s]
change:
       time:   [-1.4506% -1.3839% -1.3105] (p = 0.00 < 0.05)
       thrpt:  [+1.3279% +1.4033% +1.4720]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild

Download data for profiler.firefox.com or download performance comparison data.

@github-actions

Copy link
Copy Markdown
Contributor

Failed Interop Tests

QUIC Interop Runner, client vs. server, differences relative to main at 9ec0cc6.

neqo-pr as clientneqo-pr as server
neqo-pr vs. go-x-net: BP BA
neqo-pr vs. haproxy: BP BA
neqo-pr vs. kwik: BP BA
neqo-pr vs. lsquic: L1 C1
neqo-pr vs. msquic: A L1 🚀L2 C1
neqo-pr vs. mvfst: A BA
neqo-pr vs. neqo: A 🚀BA
neqo-pr vs. nginx: ⚠️L1 BP BA
neqo-pr vs. ngtcp2: CM
neqo-pr vs. picoquic: A
neqo-pr vs. quic-go: A
neqo-pr vs. quic-zig: B
neqo-pr vs. quiche: BP BA
neqo-pr vs. s2n-quic: 🚀BA CM
neqo-pr vs. tquic: S BP BA
neqo-pr vs. xquic: A ⚠️L1
aioquic vs. neqo-pr: baseline result missing
go-x-net vs. neqo-pr: CM
kwik vs. neqo-pr: BP BA CM
msquic vs. neqo-pr: CM
mvfst vs. neqo-pr: Z L1 C1 CM
neqo vs. neqo-pr: A
openssl vs. neqo-pr: LR M A CM
quic-go vs. neqo-pr: CM
quiche vs. neqo-pr: 🚀L1 CM
quinn vs. neqo-pr: V2 CM
s2n-quic vs. neqo-pr: ⚠️BP CM
tquic vs. neqo-pr: CM
xquic vs. neqo-pr: M CM
All results

Succeeded Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

Unsupported Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

@github-actions

Copy link
Copy Markdown
Contributor

Client/server transfer results

Performance differences relative to 9ec0cc6.

Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.

Client vs. server Mean±σ Min–Max Median±MAD MiB/s±σ ΔMedian
neqo-neqo-newreno 79.2 ± 2.9 71.7 – 88.1 78.9 ± 2.6 404.2 ± 14.9 💔 +1.2 (+1.5%)

Table above only shows statistically significant changes. See all results below.

All results

Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.

Client vs. server Mean±σ Min–Max Median±MAD MiB/s±σ ΔMedian
google-google 467.0 ± 2.3 462.8 – 476.2 466.8 ± 2.0 68.5 ± 0.3
google-neqo-cubic 275.3 ± 1.7 272.7 – 281.5 275.2 ± 1.7 116.2 ± 0.7 -0.4 (-0.2%)
neqo-google-cubic 772.1 ± 3.3 764.8 – 778.2 772.2 ± 3.4 41.4 ± 0.2 +0.2 (+0.0%)
neqo-neqo-cubic 78.4 ± 2.0 71.2 – 84.3 78.2 ± 1.8 408.4 ± 10.6 +0.4 (+0.6%)
neqo-neqo-cubic-nopacing 80.2 ± 3.2 75.7 – 91.5 79.4 ± 2.0 399.0 ± 15.7 +0.2 (+0.3%)
neqo-neqo-newreno 79.2 ± 2.9 71.7 – 88.1 78.9 ± 2.6 404.2 ± 14.9 💔 +1.2 (+1.5%)
neqo-neqo-newreno-nopacing 80.0 ± 2.7 74.9 – 92.0 79.4 ± 2.3 400.2 ± 13.4 -0.8 (-1.1%)
neqo-quiche-cubic 194.7 ± 1.5 189.7 – 200.6 194.8 ± 1.5 164.4 ± 1.3 +0.4 (+0.2%)
neqo-s2n-cubic 215.4 ± 2.0 209.1 – 221.9 215.2 ± 1.3 148.6 ± 1.4 -0.0 (-0.0%)
quiche-neqo-cubic 136.3 ± 1.9 133.8 – 143.6 135.7 ± 1.4 234.7 ± 3.2 -0.1 (-0.1%)
quiche-quiche 134.8 ± 3.4 127.5 – 143.6 135.3 ± 2.9 237.4 ± 6.0
s2n-neqo-cubic 219.0 ± 1.9 215.5 – 225.2 218.4 ± 1.7 146.1 ± 1.3 +0.2 (+0.1%)
s2n-s2n ⚠️ 289.7 ± 21.7 279.3 – 383.6 284.6 ± 2.9 110.5 ± 8.3

Download data for profiler.firefox.com or download performance comparison data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants