lsqpack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +82 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/Rakefile +19 -0
- data/Steepfile +6 -0
- data/ext/lsqpack/extconf.rb +18 -0
- data/ext/lsqpack/lsqpack.c +426 -0
- data/ext/lsqpack/lsqpack.h +6 -0
- data/lib/lsqpack/version.rb +5 -0
- data/lib/lsqpack.rb +30 -0
- data/ls-qpack/.appveyor.yml +14 -0
- data/ls-qpack/.cirrus.yml +6 -0
- data/ls-qpack/.travis.yml +32 -0
- data/ls-qpack/CMakeLists.txt +66 -0
- data/ls-qpack/LICENSE +21 -0
- data/ls-qpack/README.md +65 -0
- data/ls-qpack/bin/CMakeLists.txt +21 -0
- data/ls-qpack/bin/encode-int.c +87 -0
- data/ls-qpack/bin/fuzz-decode.c +247 -0
- data/ls-qpack/bin/interop-decode.c +433 -0
- data/ls-qpack/bin/interop-encode.c +554 -0
- data/ls-qpack/deps/xxhash/xxhash.c +941 -0
- data/ls-qpack/deps/xxhash/xxhash.h +160 -0
- data/ls-qpack/fuzz/decode/a/README +3 -0
- data/ls-qpack/fuzz/decode/a/preamble +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,sig_06,src_000390,op_havoc,rep_4 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,sig_06,src_000579,op_flip1,pos_14 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000000,src_000000,op_flip2,pos_12 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000001,sig_11,src_000579,op_havoc,rep_4 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000002,sig_11,src_000481,op_int16,pos_15,val_-1 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000002,src_000000,op_havoc,rep_8 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000006,src_000285,op_flip2,pos_14 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000008,src_000285,op_flip2,pos_20 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000010,src_000306,op_flip2,pos_75 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000011,src_000344,op_havoc,rep_2 +0 -0
- data/ls-qpack/fuzz/decode/a/test-cases/id_000014,src_000366,op_flip2,pos_28 +0 -0
- data/ls-qpack/fuzz/decode/b/README +1 -0
- data/ls-qpack/fuzz/decode/b/preamble +0 -0
- data/ls-qpack/fuzz/decode/b/test-cases/seed +0 -0
- data/ls-qpack/fuzz/decode/c/setup.sh +3 -0
- data/ls-qpack/fuzz/decode/c/test-cases/fb-req.qif.proxygen.out.256.100.0-chopped +0 -0
- data/ls-qpack/fuzz/decode/d/preamble +0 -0
- data/ls-qpack/fuzz/decode/d/setup.sh +3 -0
- data/ls-qpack/fuzz/decode/d/test-cases/fb-resp.minhq.256.128.0.ack +0 -0
- data/ls-qpack/fuzz/input/256.100.1/fb-req.out.256.100.1 +0 -0
- data/ls-qpack/fuzz/input/256.100.1/fb-resp.out.256.100.1 +0 -0
- data/ls-qpack/fuzz/input/256.100.1/netbsd.out.256.100.1 +0 -0
- data/ls-qpack/huff-tables.h +136247 -0
- data/ls-qpack/lsqpack.c +5547 -0
- data/ls-qpack/lsqpack.h +768 -0
- data/ls-qpack/test/CMakeLists.txt +76 -0
- data/ls-qpack/test/lsqpack-test.h +43 -0
- data/ls-qpack/test/qifs/fb-req.qif +4917 -0
- data/ls-qpack/test/qifs/fb-resp.qif +5982 -0
- data/ls-qpack/test/qifs/long-codes.qif +5984 -0
- data/ls-qpack/test/qifs/netbsd.qif +235 -0
- data/ls-qpack/test/run-qif.pl +97 -0
- data/ls-qpack/test/run-scenario.sh +68 -0
- data/ls-qpack/test/scenarios/0.95-reset.sce +10 -0
- data/ls-qpack/test/scenarios/cancel-stream.sce +22 -0
- data/ls-qpack/test/scenarios/drain-2.sce +37 -0
- data/ls-qpack/test/scenarios/drain.sce +37 -0
- data/ls-qpack/test/scenarios/end-dst-2.sce +14 -0
- data/ls-qpack/test/scenarios/end-dst.sce +14 -0
- data/ls-qpack/test/scenarios/incl-name.sce +13 -0
- data/ls-qpack/test/scenarios/multi-byte-int-dyn-ref-1.sce +110 -0
- data/ls-qpack/test/scenarios/multi-byte-int-dyn-ref-2.sce +161 -0
- data/ls-qpack/test/scenarios/post-base-1.sce +10 -0
- data/ls-qpack/test/scenarios/post-base-2.sce +13 -0
- data/ls-qpack/test/scenarios/post-base-nr.sce +10 -0
- data/ls-qpack/test/scenarios/set-max-cap.sce +15 -0
- data/ls-qpack/test/test_enc_str.c +139 -0
- data/ls-qpack/test/test_get_stx_id.c +144 -0
- data/ls-qpack/test/test_huff_dec.c +399 -0
- data/ls-qpack/test/test_int.c +220 -0
- data/ls-qpack/test/test_qpack.c +856 -0
- data/ls-qpack/test/test_read_enc_stream.c +256 -0
- data/ls-qpack/tools/har2qif.pl +139 -0
- data/ls-qpack/tools/randomize-cookies.pl +41 -0
- data/ls-qpack/tools/sort-qif.pl +31 -0
- data/ls-qpack/wincompat/getopt.c +758 -0
- data/ls-qpack/wincompat/getopt.h +131 -0
- data/ls-qpack/wincompat/getopt1.c +188 -0
- data/ls-qpack/wincompat/sys/queue.h +859 -0
- data/lsqpack.gemspec +39 -0
- data/sig/lsqpack.rbs +29 -0
- metadata +135 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
language: c
|
2
|
+
sudo: false
|
3
|
+
addons:
|
4
|
+
apt:
|
5
|
+
matrix:
|
6
|
+
include:
|
7
|
+
- name: Linux (gcc-8)
|
8
|
+
os: linux
|
9
|
+
dist: xenial
|
10
|
+
compiler: gcc-8
|
11
|
+
addons:
|
12
|
+
apt:
|
13
|
+
sources:
|
14
|
+
- ubuntu-toolchain-r-test
|
15
|
+
packages: g++-8
|
16
|
+
- name: Linux (clang)
|
17
|
+
os: linux
|
18
|
+
dist: xenial
|
19
|
+
compiler: clang
|
20
|
+
- name: macOS (xcode)
|
21
|
+
os: osx
|
22
|
+
- name: macOS (xcode 10.1)
|
23
|
+
os: osx
|
24
|
+
image: xcode10.1
|
25
|
+
before_install:
|
26
|
+
- $CC --version
|
27
|
+
- cmake --version
|
28
|
+
before_script:
|
29
|
+
- cmake -DLSQPACK_TESTS=ON .
|
30
|
+
script:
|
31
|
+
- make
|
32
|
+
- make test
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# The following variable can be defined on the command line:
|
2
|
+
#
|
3
|
+
# BUILD_SHARED_LIBS
|
4
|
+
#
|
5
|
+
# The following environment variables will be taken into account when running
|
6
|
+
# cmake for the first time:
|
7
|
+
#
|
8
|
+
# CFLAGS
|
9
|
+
# LDFLAGS
|
10
|
+
|
11
|
+
cmake_minimum_required(VERSION 3.1)
|
12
|
+
project(ls-qpack LANGUAGES C)
|
13
|
+
|
14
|
+
option(LSQPACK_TESTS "Build tests")
|
15
|
+
option(LSQPACK_BIN "Build binaries" ON)
|
16
|
+
option(LSQPACK_XXH "Include XXH" ON)
|
17
|
+
|
18
|
+
# Use `cmake -DBUILD_SHARED_LIBS=OFF` to build a static library.
|
19
|
+
add_library(ls-qpack "")
|
20
|
+
target_include_directories(ls-qpack PUBLIC .)
|
21
|
+
target_sources(ls-qpack PRIVATE lsqpack.c)
|
22
|
+
|
23
|
+
target_include_directories(ls-qpack PRIVATE deps/xxhash/)
|
24
|
+
if(LSQPACK_XXH)
|
25
|
+
target_sources(ls-qpack PRIVATE deps/xxhash/xxhash.c)
|
26
|
+
endif()
|
27
|
+
|
28
|
+
if(MSVC)
|
29
|
+
target_include_directories(ls-qpack PUBLIC wincompat)
|
30
|
+
endif()
|
31
|
+
|
32
|
+
if(MSVC)
|
33
|
+
target_compile_options(ls-qpack PRIVATE
|
34
|
+
/Wall
|
35
|
+
/wd4100 # unreffed parameter
|
36
|
+
/wd4200 # zero-sized array
|
37
|
+
# Apparently this C99 construct is not supported properly by VS:
|
38
|
+
# https://stackoverflow.com/questions/1064930/struct-initializer-typedef-with-visual-studio
|
39
|
+
/wd4204 # non-constant aggregate initializer
|
40
|
+
/wd4255 # no function prototype (getopt)
|
41
|
+
/wd4820 # padding
|
42
|
+
/wd4668 # undefined macro
|
43
|
+
/wd4710 # not inlined by default
|
44
|
+
/wd4996 # unsafe function
|
45
|
+
)
|
46
|
+
else()
|
47
|
+
target_compile_options(ls-qpack PRIVATE
|
48
|
+
-Wall
|
49
|
+
-Wextra
|
50
|
+
-Wno-unused-parameter
|
51
|
+
-fno-omit-frame-pointer
|
52
|
+
)
|
53
|
+
endif()
|
54
|
+
|
55
|
+
IF (CMAKE_BUILD_TYPE STREQUAL MinSizeRel)
|
56
|
+
SET(CMAKE_C_FLAGS "${CMAKE_C_CFLAGS} -DLS_QPACK_USE_LARGE_TABLES=0")
|
57
|
+
ENDIF()
|
58
|
+
|
59
|
+
if(LSQPACK_TESTS)
|
60
|
+
enable_testing()
|
61
|
+
add_subdirectory(test)
|
62
|
+
endif()
|
63
|
+
|
64
|
+
if(LSQPACK_BIN)
|
65
|
+
add_subdirectory(bin)
|
66
|
+
endif()
|
data/ls-qpack/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 - 2020 LiteSpeed Tech
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/ls-qpack/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
[](https://travis-ci.org/litespeedtech/ls-qpack)
|
2
|
+
[](https://ci.appveyor.com/project/litespeedtech/ls-qpack)
|
3
|
+
[](https://cirrus-ci.com/github/litespeedtech/ls-qpack)
|
4
|
+
|
5
|
+
# ls-qpack
|
6
|
+
QPACK compression library for use with HTTP/3
|
7
|
+
|
8
|
+
## Introduction
|
9
|
+
|
10
|
+
QPACK is the compression mechanism used by
|
11
|
+
[HTTP/3](https://en.wikipedia.org/wiki/HTTP/3) to compress HTTP headers.
|
12
|
+
It is in the process of being standardazed by the QUIC Working Group. The
|
13
|
+
[QPACK Internet-Draft](https://tools.ietf.org/html/draft-ietf-quic-qpack-11)
|
14
|
+
is has been stable for some time and we don't expect functional changes to
|
15
|
+
it before the final RFC is released.
|
16
|
+
|
17
|
+
## Functionality
|
18
|
+
|
19
|
+
ls-qpack is a full-featured, tested, and fast QPACK library. The QPACK encoder
|
20
|
+
produces excellent compression results based on an innovative mnemonic technique
|
21
|
+
(to be described in a future article). It boasts the fastest Huffman
|
22
|
+
[encoder](https://blog.litespeedtech.com/2019/10/03/fast-huffman-encoder/) and
|
23
|
+
[decoder](https://blog.litespeedtech.com/2019/09/16/fast-huffman-decoder/).
|
24
|
+
|
25
|
+
The library is production quality. It is used in
|
26
|
+
[OpenLiteSpeed](https://openlitespeed.org/),
|
27
|
+
LiteSpeed [Web Server](https://www.litespeedtech.com/products#lsws),
|
28
|
+
and LiteSpeed [Web ADC](https://www.litespeedtech.com/products#wadc).
|
29
|
+
|
30
|
+
The library is robust:
|
31
|
+
1. The encoder does not assume anything about usual HTTP headers such as `Server`
|
32
|
+
or `User-Agent`. Instead, it uses its mnemonic compression technique to
|
33
|
+
achieve good compression results for any input.
|
34
|
+
1. The decoder uses modulo arithmetic to track dynamic table insertions. This is
|
35
|
+
in contrast to all other QPACK implementations, which use an integer counter,
|
36
|
+
meaning that at some point, the decoder will break.
|
37
|
+
1. The decoder processes input in streaming fashion. The caller does not have to
|
38
|
+
buffer the contents of HTTP/3 `HEADERS` frame. Instead, the decoder can be
|
39
|
+
supplied input byte-by-byte.
|
40
|
+
|
41
|
+
## Other Languages
|
42
|
+
|
43
|
+
The ls-qpack library is implemented in vanilla C99. It makes it a good candidate
|
44
|
+
for wrapping into a library for a higher-level language. As of this writing, we
|
45
|
+
know of the following wrappers:
|
46
|
+
- Go: [ls-qpack-go](https://github.com/mpiraux/ls-qpack-go)
|
47
|
+
- Python: [pylsqpack](https://github.com/aiortc/pylsqpack)
|
48
|
+
- TypeScript: [quicker](https://github.com/rmarx/quicker/tree/draft-20/lib/ls-qpack)
|
49
|
+
|
50
|
+
## Versioning
|
51
|
+
|
52
|
+
Before the QPACK RFC is released, the three parts of the version are:
|
53
|
+
- MAJOR: set to zero;
|
54
|
+
- MINOR: set to the number of QPACK Internet-Draft the lirbary supports; and
|
55
|
+
- PATCH: set to the patch number
|
56
|
+
|
57
|
+
Once the RFC is released, MARJO will be set to 1 and the version will follow
|
58
|
+
the usual MAJOR.MINOR.PATCH pattern.
|
59
|
+
|
60
|
+
## API
|
61
|
+
|
62
|
+
The API is documented in the header file, [lsqpack.h](lsqpack.h).
|
63
|
+
One example how it is used in real code can be seen in
|
64
|
+
[lsquic](https://github.com/litespeedtech/lsquic), a QUIC and HTTP/3 library
|
65
|
+
developed by LiteSpeed Technologies.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
function(lsqpack_add_executable TARGET)
|
2
|
+
add_executable(${TARGET} "")
|
3
|
+
target_link_libraries(${TARGET} PRIVATE ls-qpack)
|
4
|
+
|
5
|
+
target_sources(${TARGET} PRIVATE ${TARGET}.c)
|
6
|
+
|
7
|
+
if(MSVC)
|
8
|
+
target_include_directories(${TARGET} PRIVATE ../wincompat)
|
9
|
+
target_sources(${TARGET} PRIVATE
|
10
|
+
../wincompat/getopt.c
|
11
|
+
../wincompat/getopt1.c
|
12
|
+
)
|
13
|
+
else()
|
14
|
+
target_link_libraries(${TARGET} PRIVATE m)
|
15
|
+
endif()
|
16
|
+
endfunction()
|
17
|
+
|
18
|
+
lsqpack_add_executable(interop-encode)
|
19
|
+
lsqpack_add_executable(interop-decode)
|
20
|
+
lsqpack_add_executable(encode-int)
|
21
|
+
lsqpack_add_executable(fuzz-decode)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/* encode-int: encode an integer into HPACK varint. */
|
2
|
+
|
3
|
+
#include <assert.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
|
9
|
+
static unsigned char *
|
10
|
+
enc_int (unsigned char *dst, unsigned char *const end, uint64_t value,
|
11
|
+
unsigned prefix_bits)
|
12
|
+
{
|
13
|
+
unsigned char *const dst_orig = dst;
|
14
|
+
|
15
|
+
/* This function assumes that at least one byte is available */
|
16
|
+
assert(dst < end);
|
17
|
+
if (value < (1u << prefix_bits) - 1)
|
18
|
+
*dst++ |= value;
|
19
|
+
else
|
20
|
+
{
|
21
|
+
*dst++ |= (1 << prefix_bits) - 1;
|
22
|
+
value -= (1 << prefix_bits) - 1;
|
23
|
+
while (value >= 128)
|
24
|
+
{
|
25
|
+
if (dst < end)
|
26
|
+
{
|
27
|
+
*dst++ = 0x80 | (unsigned char) value;
|
28
|
+
value >>= 7;
|
29
|
+
}
|
30
|
+
else
|
31
|
+
return dst_orig;
|
32
|
+
}
|
33
|
+
if (dst < end)
|
34
|
+
*dst++ = (unsigned char) value;
|
35
|
+
else
|
36
|
+
return dst_orig;
|
37
|
+
}
|
38
|
+
return dst;
|
39
|
+
}
|
40
|
+
|
41
|
+
static unsigned
|
42
|
+
lsqpack_val2len (uint64_t value, unsigned prefix_bits)
|
43
|
+
{
|
44
|
+
uint64_t mask = (1ULL << prefix_bits) - 1;
|
45
|
+
return 1
|
46
|
+
+ (value >= mask )
|
47
|
+
+ (value >= ((1ULL << 7) + mask))
|
48
|
+
+ (value >= ((1ULL << 14) + mask))
|
49
|
+
+ (value >= ((1ULL << 21) + mask))
|
50
|
+
+ (value >= ((1ULL << 28) + mask))
|
51
|
+
+ (value >= ((1ULL << 35) + mask))
|
52
|
+
+ (value >= ((1ULL << 42) + mask))
|
53
|
+
+ (value >= ((1ULL << 49) + mask))
|
54
|
+
+ (value >= ((1ULL << 56) + mask))
|
55
|
+
+ (value >= ((1ULL << 63) + mask))
|
56
|
+
;
|
57
|
+
}
|
58
|
+
|
59
|
+
int
|
60
|
+
main (int argc, char **argv)
|
61
|
+
{
|
62
|
+
unsigned long long val;
|
63
|
+
unsigned char *p;
|
64
|
+
unsigned prefix_bits;
|
65
|
+
unsigned char buf[20];
|
66
|
+
|
67
|
+
if (argc != 3)
|
68
|
+
{
|
69
|
+
fprintf(stderr, "Usage: %s prefix_bits value\n", argv[0]);
|
70
|
+
exit(EXIT_FAILURE);
|
71
|
+
}
|
72
|
+
|
73
|
+
prefix_bits = atoi(argv[1]);
|
74
|
+
val = strtoull(argv[2], NULL, 10);
|
75
|
+
|
76
|
+
fprintf(stderr, "expected size: %u\n", lsqpack_val2len(val, prefix_bits));
|
77
|
+
buf[0] = 0;
|
78
|
+
p = enc_int(buf, buf + sizeof(buf), val, prefix_bits);
|
79
|
+
|
80
|
+
if (p > buf)
|
81
|
+
{
|
82
|
+
fwrite(buf, 1, p - buf, stdout);
|
83
|
+
exit(EXIT_SUCCESS);
|
84
|
+
}
|
85
|
+
else
|
86
|
+
exit(EXIT_FAILURE);
|
87
|
+
}
|
@@ -0,0 +1,247 @@
|
|
1
|
+
/*
|
2
|
+
* fuzz-decode: special program for fuzzing. It still reads encoded
|
3
|
+
* files just like interop-decode, but tries to do it faster and
|
4
|
+
* forgoes several advanced options.
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifdef WIN32
|
8
|
+
|
9
|
+
#include <stdio.h>
|
10
|
+
|
11
|
+
int
|
12
|
+
main (int argc, char **argv)
|
13
|
+
{
|
14
|
+
fprintf(stderr, "%s is not supported on Windows: need mmap(2)\n", argv[0]);
|
15
|
+
return 1;
|
16
|
+
}
|
17
|
+
|
18
|
+
#else
|
19
|
+
|
20
|
+
#include <assert.h>
|
21
|
+
|
22
|
+
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
23
|
+
#include <sys/endian.h>
|
24
|
+
#define bswap_16 bswap16
|
25
|
+
#define bswap_32 bswap32
|
26
|
+
#define bswap_64 bswap64
|
27
|
+
#elif defined(__APPLE__)
|
28
|
+
#include <libkern/OSByteOrder.h>
|
29
|
+
#define bswap_16 OSSwapInt16
|
30
|
+
#define bswap_32 OSSwapInt32
|
31
|
+
#define bswap_64 OSSwapInt64
|
32
|
+
#elif defined(WIN32)
|
33
|
+
#define bswap_16 _byteswap_ushort
|
34
|
+
#define bswap_32 _byteswap_ulong
|
35
|
+
#define bswap_64 _byteswap_uint64
|
36
|
+
#else
|
37
|
+
#include <byteswap.h>
|
38
|
+
#endif
|
39
|
+
|
40
|
+
#include <errno.h>
|
41
|
+
#include <inttypes.h>
|
42
|
+
#include <stdio.h>
|
43
|
+
#include <stdlib.h>
|
44
|
+
#include <string.h>
|
45
|
+
#include <unistd.h>
|
46
|
+
#include <sys/queue.h>
|
47
|
+
#include <sys/types.h>
|
48
|
+
#include <sys/stat.h>
|
49
|
+
#include <sys/mman.h>
|
50
|
+
#include <fcntl.h>
|
51
|
+
|
52
|
+
#include "lsqpack.h"
|
53
|
+
|
54
|
+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
55
|
+
|
56
|
+
static void
|
57
|
+
usage (const char *name)
|
58
|
+
{
|
59
|
+
fprintf(stderr,
|
60
|
+
"Usage: %s [options] [-i input] [-o output]\n"
|
61
|
+
"\n"
|
62
|
+
"Options:\n"
|
63
|
+
" -i FILE Input file.\n"
|
64
|
+
" -f FILE Fuzz file: this is the stuff the fuzzer will change.\n"
|
65
|
+
" -s NUMBER Maximum number of risked streams. Defaults to %u.\n"
|
66
|
+
" -t NUMBER Dynamic table size. Defaults to %u.\n"
|
67
|
+
"\n"
|
68
|
+
" -h Print this help screen and exit\n"
|
69
|
+
, name, LSQPACK_DEF_MAX_RISKED_STREAMS, LSQPACK_DEF_DYN_TABLE_SIZE);
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
static void
|
74
|
+
hblock_unblocked (void *buf_p)
|
75
|
+
{
|
76
|
+
exit(1);
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
int
|
81
|
+
main (int argc, char **argv)
|
82
|
+
{
|
83
|
+
int in_fd = -1, fuzz_fd = STDIN_FILENO;
|
84
|
+
int opt;
|
85
|
+
unsigned dyn_table_size = LSQPACK_DEF_DYN_TABLE_SIZE,
|
86
|
+
max_risked_streams = LSQPACK_DEF_MAX_RISKED_STREAMS;
|
87
|
+
struct lsqpack_dec decoder;
|
88
|
+
const unsigned char *p, *end;
|
89
|
+
unsigned char *begin;
|
90
|
+
struct stat st;
|
91
|
+
uint64_t stream_id;
|
92
|
+
uint32_t size;
|
93
|
+
int r;
|
94
|
+
|
95
|
+
while (-1 != (opt = getopt(argc, argv, "i:f:s:t:h")))
|
96
|
+
{
|
97
|
+
switch (opt)
|
98
|
+
{
|
99
|
+
case 'i':
|
100
|
+
in_fd = open(optarg, O_RDONLY);
|
101
|
+
if (in_fd < 0)
|
102
|
+
{
|
103
|
+
fprintf(stderr, "cannot open `%s' for reading: %s\n",
|
104
|
+
optarg, strerror(errno));
|
105
|
+
exit(EXIT_FAILURE);
|
106
|
+
}
|
107
|
+
break;
|
108
|
+
case 'f':
|
109
|
+
fuzz_fd = open(optarg, O_RDONLY);
|
110
|
+
if (fuzz_fd < 0)
|
111
|
+
{
|
112
|
+
fprintf(stderr, "cannot open `%s' for reading: %s\n",
|
113
|
+
optarg, strerror(errno));
|
114
|
+
exit(EXIT_FAILURE);
|
115
|
+
}
|
116
|
+
break;
|
117
|
+
case 's':
|
118
|
+
max_risked_streams = atoi(optarg);
|
119
|
+
break;
|
120
|
+
case 't':
|
121
|
+
dyn_table_size = atoi(optarg);
|
122
|
+
break;
|
123
|
+
case 'h':
|
124
|
+
usage(argv[0]);
|
125
|
+
exit(EXIT_SUCCESS);
|
126
|
+
default:
|
127
|
+
exit(EXIT_FAILURE);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
lsqpack_dec_init(&decoder, NULL, dyn_table_size, max_risked_streams,
|
132
|
+
hblock_unblocked);
|
133
|
+
|
134
|
+
if (in_fd < 0)
|
135
|
+
{
|
136
|
+
fprintf(stderr, "Specify input using `-i' option\n");
|
137
|
+
exit(1);
|
138
|
+
}
|
139
|
+
|
140
|
+
if (0 != fstat(in_fd, &st))
|
141
|
+
{
|
142
|
+
perror("fstat");
|
143
|
+
exit(1);
|
144
|
+
}
|
145
|
+
|
146
|
+
begin = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in_fd, 0);
|
147
|
+
if (!begin)
|
148
|
+
{
|
149
|
+
perror("mmap");
|
150
|
+
exit(1);
|
151
|
+
}
|
152
|
+
|
153
|
+
p = begin;
|
154
|
+
end = begin + st.st_size;
|
155
|
+
while (p + sizeof(stream_id) + sizeof(size) < end)
|
156
|
+
{
|
157
|
+
stream_id = * (uint64_t *) p;
|
158
|
+
p += sizeof(uint64_t);
|
159
|
+
size = * (uint32_t *) p;
|
160
|
+
p += sizeof(uint32_t);
|
161
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
162
|
+
stream_id = bswap_64(stream_id);
|
163
|
+
size = bswap_32(size);
|
164
|
+
#endif
|
165
|
+
if (p + size > end)
|
166
|
+
{
|
167
|
+
fprintf(stderr, "truncated input at offset %u",
|
168
|
+
(unsigned) (p - begin));
|
169
|
+
abort();
|
170
|
+
}
|
171
|
+
if (stream_id == 0)
|
172
|
+
{
|
173
|
+
r = lsqpack_dec_enc_in(&decoder, p, size);
|
174
|
+
if (r != 0)
|
175
|
+
abort();
|
176
|
+
}
|
177
|
+
else
|
178
|
+
{
|
179
|
+
const unsigned char *cur = p;
|
180
|
+
struct lsqpack_header_list *hlist;
|
181
|
+
enum lsqpack_read_header_status rhs;
|
182
|
+
rhs = lsqpack_dec_header_in(&decoder, NULL, stream_id,
|
183
|
+
size, &cur, size, &hlist, NULL, NULL);
|
184
|
+
if (rhs != LQRHS_DONE || (uint32_t) (cur - p) != size)
|
185
|
+
abort();
|
186
|
+
lsqpack_dec_destroy_header_list(hlist);
|
187
|
+
}
|
188
|
+
p += size;
|
189
|
+
}
|
190
|
+
|
191
|
+
munmap(begin, st.st_size);
|
192
|
+
(void) close(in_fd);
|
193
|
+
|
194
|
+
/* Now let's read the fuzzed part */
|
195
|
+
|
196
|
+
if (0 != fstat(fuzz_fd, &st))
|
197
|
+
{
|
198
|
+
perror("fstat");
|
199
|
+
exit(1);
|
200
|
+
}
|
201
|
+
|
202
|
+
begin = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fuzz_fd, 0);
|
203
|
+
if (!begin)
|
204
|
+
{
|
205
|
+
perror("mmap");
|
206
|
+
exit(1);
|
207
|
+
}
|
208
|
+
|
209
|
+
p = begin;
|
210
|
+
end = begin + st.st_size;
|
211
|
+
while (p + sizeof(stream_id) + sizeof(size) < end)
|
212
|
+
{
|
213
|
+
stream_id = * (uint64_t *) p;
|
214
|
+
p += sizeof(uint64_t);
|
215
|
+
size = * (uint32_t *) p;
|
216
|
+
p += sizeof(uint32_t);
|
217
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
218
|
+
stream_id = bswap_64(stream_id);
|
219
|
+
size = bswap_32(size);
|
220
|
+
#endif
|
221
|
+
if (stream_id == 0)
|
222
|
+
{
|
223
|
+
r = lsqpack_dec_enc_in(&decoder, p, MIN(size, (uint32_t) (end - p)));
|
224
|
+
(void) r;
|
225
|
+
}
|
226
|
+
else
|
227
|
+
{
|
228
|
+
const unsigned char *cur = p;
|
229
|
+
struct lsqpack_header_list *hlist;
|
230
|
+
enum lsqpack_read_header_status rhs;
|
231
|
+
size = MIN(size, (uint32_t) (end - p));
|
232
|
+
rhs = lsqpack_dec_header_in(&decoder, NULL, stream_id,
|
233
|
+
size, &cur, size, &hlist, NULL, NULL);
|
234
|
+
(void) rhs;
|
235
|
+
}
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
|
239
|
+
munmap(begin, st.st_size);
|
240
|
+
(void) close(fuzz_fd);
|
241
|
+
|
242
|
+
lsqpack_dec_cleanup(&decoder);
|
243
|
+
|
244
|
+
exit(0);
|
245
|
+
}
|
246
|
+
|
247
|
+
#endif
|