Skip to content

Commit 72af1ed

Browse files
Ruben2424Peter Michael Green
and
Peter Michael Green
authored
Integer overflow when parsing prefixed integers from qpack (#301)
* add testcase * apply patch from issue * update ci to also test 32bit * fix MAX_POWER value and make sure 62 bit integers can still be processed * fix existing tests with are no longer in the allowed range * CI should install build tools * test examples not as rust integration test. Instead run shell script in ci. --------- Co-authored-by: Peter Michael Green <[email protected]>
1 parent 09342bc commit 72af1ed

File tree

4 files changed

+91
-62
lines changed

4 files changed

+91
-62
lines changed

.github/workflows/CI.yml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ jobs:
2626
- test
2727
- doc
2828
- fuzz
29+
- examples
30+
- compliance
2931
steps:
3032
- run: exit 0
3133

@@ -105,28 +107,43 @@ jobs:
105107
args: -p h3-quinn
106108

107109
test:
108-
name: Test ${{ matrix.toolchain }} ${{ matrix.os }}
110+
name: Test ${{ matrix.toolchain }} ${{ matrix.os }} ${{ matrix.target }}
109111
needs: [style]
110112
strategy:
111113
matrix:
112114
os: [ubuntu-latest]
113115
toolchain: [stable, beta]
114116
features: [i-implement-a-third-party-backend-and-opt-into-breaking-changes, tracing, 'tracing,i-implement-a-third-party-backend-and-opt-into-breaking-changes']
117+
target: [x86_64-unknown-linux-gnu]
118+
include:
119+
# Add a 32-bit target test configuration
120+
- os: ubuntu-latest
121+
toolchain: stable
122+
features: i-implement-a-third-party-backend-and-opt-into-breaking-changes
123+
target: i686-unknown-linux-gnu
115124
runs-on: ${{ matrix.os }}
116125
steps:
117126
- uses: actions/checkout@v3
127+
# Add this step for 32-bit build support
128+
- name: Install 32-bit development libraries
129+
if: matrix.target == 'i686-unknown-linux-gnu'
130+
run: |
131+
sudo dpkg --add-architecture i386
132+
sudo apt-get update
133+
sudo apt-get install -y gcc-multilib libc6-dev-i386
118134
- name: Install Rust ${{ matrix.toolchain }}
119135
uses: actions-rs/toolchain@v1
120136
with:
121137
profile: minimal
122138
toolchain: ${{ matrix.toolchain }}
139+
target: ${{ matrix.target }}
123140
override: true
124141
- uses: Swatinem/rust-cache@v2
125142
- name: cargo test
126143
uses: actions-rs/cargo@v1
127144
with:
128145
command: test
129-
args: --features ${{ matrix.features }}
146+
args: --features ${{ matrix.features }} --target ${{ matrix.target }}
130147
- name: h3Spec
131148
run: ./ci/h3spec.sh
132149
if: matrix.toolchain == 'stable'
@@ -186,3 +203,19 @@ jobs:
186203
uses: ./.github/actions/compliance
187204
with:
188205
report-script: ${{ github.workspace }}/ci/compliance/report.sh
206+
207+
examples:
208+
name: Run Examples
209+
needs: [test]
210+
runs-on: ubuntu-latest
211+
steps:
212+
- uses: actions/checkout@v3
213+
- name: Install Rust stable
214+
uses: actions-rs/toolchain@v1
215+
with:
216+
profile: minimal
217+
toolchain: stable
218+
override: true
219+
- uses: Swatinem/rust-cache@v2
220+
- name: Run server and client examples test
221+
run: ./ci/example_test.sh

ci/example_test.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
set -eo pipefail
3+
4+
# Change to the repository root directory
5+
cd "$(dirname "$0")/.."
6+
7+
# Start the server in the background
8+
echo "Starting server..."
9+
cargo run --example server -- --listen=[::]:4433 --cert=examples/server.cert --key=examples/server.key &
10+
SERVER_PID=$!
11+
12+
# Wait for the server to start
13+
sleep 2
14+
15+
# Function to clean up server process on exit
16+
cleanup() {
17+
echo "Cleaning up server process..."
18+
kill $SERVER_PID 2>/dev/null || true
19+
}
20+
21+
# Set up cleanup on script exit
22+
trap cleanup EXIT
23+
24+
# Run the client
25+
echo "Running client..."
26+
cargo run --example client -- https://localhost:4433 --ca=examples/ca.cert
27+
28+
# If we got here, the test succeeded
29+
echo "Server and client connected successfully!"
30+
exit 0

h3/src/qpack/prefix_int.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,7 @@ pub fn encode<B: BufMut>(size: u8, flags: u8, value: u64, buf: &mut B) {
7777
buf.write(remaining as u8);
7878
}
7979

80-
#[cfg(target_pointer_width = "64")]
81-
const MAX_POWER: usize = 10 * 7;
82-
83-
#[cfg(target_pointer_width = "32")]
84-
const MAX_POWER: usize = 5 * 7;
80+
const MAX_POWER: usize = 9 * 7;
8581

8682
impl From<coding::UnexpectedEnd> for Error {
8783
fn from(_: coding::UnexpectedEnd) -> Self {
@@ -91,8 +87,11 @@ impl From<coding::UnexpectedEnd> for Error {
9187

9288
#[cfg(test)]
9389
mod test {
90+
use assert_matches::assert_matches;
9491
use std::io::Cursor;
9592

93+
use crate::qpack::prefix_int::Error;
94+
9695
fn check_codec(size: u8, flags: u8, value: u64, data: &[u8]) {
9796
let mut buf = Vec::new();
9897
super::encode(size, flags, value, &mut buf);
@@ -110,8 +109,8 @@ mod test {
110109
check_codec(
111110
5,
112111
0b010,
113-
u64::max_value(),
114-
&[95, 224, 255, 255, 255, 255, 255, 255, 255, 255, 1],
112+
0x80_00_00_00_00_00_00_1E,
113+
&[95, 255, 255, 255, 255, 255, 255, 255, 255, 127],
115114
);
116115
}
117116

@@ -122,8 +121,8 @@ mod test {
122121
check_codec(
123122
8,
124123
0,
125-
u64::max_value(),
126-
&[255, 128, 254, 255, 255, 255, 255, 255, 255, 255, 1],
124+
0x80_00_00_00_00_00_00_FE,
125+
&[255, 255, 255, 255, 255, 255, 255, 255, 255, 127],
127126
);
128127
}
129128

@@ -154,4 +153,22 @@ mod test {
154153
fn number_never_ends_with_0x80() {
155154
check_codec(4, 0b0001, 143, &[31, 128, 1]);
156155
}
156+
#[test]
157+
fn overflow2() {
158+
let buf = vec![95, 225, 255, 255, 255, 255, 255, 255, 255, 255, 1];
159+
let mut read = Cursor::new(&buf);
160+
let x = super::decode(5, &mut read);
161+
assert_matches!(x, Err(Error::Overflow));
162+
}
163+
164+
#[test]
165+
fn allow_62_bit() {
166+
// This is the maximum value that can be encoded in with a flag size of 7 bits
167+
// The value is requires more than 62 bits so the spec is fulfilled
168+
let buf = vec![3, 255, 255, 255, 255, 255, 255, 255, 255, 127];
169+
let mut read = Cursor::new(&buf);
170+
let (flag, value) = super::decode(1, &mut read).expect("Value is allowed to be parsed");
171+
assert_eq!(flag, 1);
172+
assert_eq!(value, 9223372036854775808);
173+
}
157174
}

h3/tests/examples_server_client.rs

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)