diff --git a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h index d3dd9217d4b0..77ae851ae594 100644 --- a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h +++ b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/nghttp3.h @@ -1871,12 +1871,13 @@ typedef struct nghttp3_settings { NGHTTP3_SETTINGS_V3. */ /** * :member:`glitch_ratelim_burst` is the maximum number of tokens - * available to "glitch" rate limiter. "glitch" is a suspicious - * activity from a remote endpoint. If detected, certain amount of - * tokens are consumed. If no tokens are available to consume, the - * connection is closed. The rate of token generation is specified - * by :member:`glitch_ratelim_rate`. This feature is enabled only - * when `nghttp3_conn_read_stream2` is used. + * available to "glitch" rate limiter. It is clamped to UINT64_MAX + * / NGHTTP3_SECONDS. "glitch" is a suspicious activity from a + * remote endpoint. If detected, certain amount of tokens are + * consumed. If no tokens are available to consume, the connection + * is closed. The rate of token generation is specified by + * :member:`glitch_ratelim_rate`. This feature is enabled only when + * `nghttp3_conn_read_stream2` is used. * * .. version-added:: 1.12.0 */ @@ -3089,6 +3090,8 @@ typedef struct nghttp3_data_reader { * Stream has already been opened. * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * The required memory for |nva| of length |nvlen| is too large. */ NGHTTP3_EXTERN int nghttp3_conn_submit_request( nghttp3_conn *conn, int64_t stream_id, const nghttp3_nv *nva, size_t nvlen, @@ -3108,6 +3111,8 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_request( * Stream not found * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * The required memory for |nva| of length |nvlen| is too large. */ NGHTTP3_EXTERN int nghttp3_conn_submit_info(nghttp3_conn *conn, int64_t stream_id, @@ -3130,6 +3135,8 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_info(nghttp3_conn *conn, * Stream not found * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * The required memory for |nva| of length |nvlen| is too large. */ NGHTTP3_EXTERN int nghttp3_conn_submit_response(nghttp3_conn *conn, int64_t stream_id, @@ -3154,6 +3161,8 @@ NGHTTP3_EXTERN int nghttp3_conn_submit_response(nghttp3_conn *conn, * Application has already submitted fin to stream. * :macro:`NGHTTP3_ERR_NOMEM` * Out of memory. + * :macro:`NGHTTP3_ERR_INVALID_ARGUMENT` + * The required memory for |nva| of length |nvlen| is too large. */ NGHTTP3_EXTERN int nghttp3_conn_submit_trailers(nghttp3_conn *conn, int64_t stream_id, diff --git a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/version.h b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/version.h index adb41c1c7b2d..f362bd4f6ba8 100644 --- a/deps/ngtcp2/nghttp3/lib/includes/nghttp3/version.h +++ b/deps/ngtcp2/nghttp3/lib/includes/nghttp3/version.h @@ -31,7 +31,7 @@ * * Version number of the nghttp3 library release. */ -#define NGHTTP3_VERSION "1.18.0" +#define NGHTTP3_VERSION "1.19.0" /** * @macro @@ -41,6 +41,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGHTTP3_VERSION_NUM 0x011200 +#define NGHTTP3_VERSION_NUM 0x011300 #endif /* !defined(NGHTTP3_VERSION_H) */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_balloc.c b/deps/ngtcp2/nghttp3/lib/nghttp3_balloc.c index 436310633349..7750263242ec 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_balloc.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_balloc.c @@ -67,7 +67,7 @@ int nghttp3_balloc_get(nghttp3_balloc *balloc, void **pbuf, size_t n) { if (nghttp3_buf_left(&balloc->buf) < n) { p = nghttp3_mem_malloc(balloc->mem, - sizeof(nghttp3_memblock_hd) + 0x8U + balloc->blklen); + sizeof(nghttp3_memblock_hd) + 0xFU + balloc->blklen); if (p == NULL) { return NGHTTP3_ERR_NOMEM; } diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_buf.c b/deps/ngtcp2/nghttp3/lib/nghttp3_buf.c index 8c33ccdb153f..7c3296cd1efb 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_buf.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_buf.c @@ -25,13 +25,15 @@ */ #include "nghttp3_buf.h" -void nghttp3_buf_init(nghttp3_buf *buf) { - buf->begin = buf->end = buf->pos = buf->last = NULL; -} +void nghttp3_buf_init(nghttp3_buf *buf) { *buf = (nghttp3_buf){0}; } void nghttp3_buf_wrap_init(nghttp3_buf *buf, uint8_t *src, size_t len) { - buf->begin = buf->pos = buf->last = src; - buf->end = buf->begin + len; + *buf = (nghttp3_buf){ + .begin = src, + .end = src + len, + .pos = src, + .last = src, + }; } void nghttp3_buf_free(nghttp3_buf *buf, const nghttp3_mem *mem) { diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c index 04b50ac3b632..8b15fb743bd9 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_conn.c @@ -555,13 +555,14 @@ nghttp3_ssize nghttp3_conn_read_stream2(nghttp3_conn *conn, int64_t stream_id, return 0; } + if (fin) { + stream->flags |= NGHTTP3_STREAM_FLAG_READ_EOF; + } + if (nghttp3_stream_uni(stream_id)) { return nghttp3_conn_read_uni(conn, stream, src, srclen, fin, ts); } - if (fin) { - stream->flags |= NGHTTP3_STREAM_FLAG_READ_EOF; - } return nghttp3_conn_read_bidi(conn, &bidi_nproc, stream, src, srclen, fin, ts); } @@ -1126,6 +1127,13 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, break; } + /* Apply buffer limits here even if everything is in the input + buffer. */ + if (rstate->left > sizeof(conn->rx.pri_fieldbuf)) { + rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME; + break; + } + conn->rx.pri_fieldbuflen = 0; rstate->state = NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE; @@ -1141,22 +1149,12 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn, len = (size_t)nghttp3_min(rstate->left, (uint64_t)(end - p)); assert(len > 0); if (conn->rx.pri_fieldbuflen == 0 && rstate->left == len) { - /* Everything is in the input buffer. Apply same length - limit we impose when buffering the field. */ - if (len > sizeof(conn->rx.pri_fieldbuf)) { - busy = 1; - rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME; - break; - } - + /* Everything is in the input buffer. */ pri_field_value = p; pri_field_valuelen = len; - } else if (len + conn->rx.pri_fieldbuflen > - sizeof(conn->rx.pri_fieldbuf)) { - busy = 1; - rstate->state = NGHTTP3_CTRL_STREAM_STATE_IGN_FRAME; - break; } else { + assert(len + conn->rx.pri_fieldbuflen <= sizeof(conn->rx.pri_fieldbuf)); + memcpy(conn->rx.pri_fieldbuf + conn->rx.pri_fieldbuflen, p, len); conn->rx.pri_fieldbuflen += len; @@ -1975,6 +1973,12 @@ int nghttp3_conn_on_settings_entry_received(nghttp3_conn *conn, break; } +#if SIZE_MAX < UINT64_MAX + if (ent->value > SIZE_MAX) { + return NGHTTP3_ERR_H3_SETTINGS_ERROR; + } +#endif /* SIZE_MAX < UINT64_MAX */ + dest->qpack_max_dtable_capacity = (size_t)ent->value; nghttp3_qpack_encoder_set_max_dtable_capacity(&conn->qenc, @@ -1989,6 +1993,12 @@ int nghttp3_conn_on_settings_entry_received(nghttp3_conn *conn, break; } +#if SIZE_MAX < UINT64_MAX + if (ent->value > SIZE_MAX) { + return NGHTTP3_ERR_H3_SETTINGS_ERROR; + } +#endif /* SIZE_MAX < UINT64_MAX */ + dest->qpack_blocked_streams = (size_t)ent->value; nghttp3_qpack_encoder_set_max_blocked_streams( @@ -2957,6 +2967,8 @@ int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn, memcpy(buf, data, datalen); } + assert(conn->tx.ctrl); + rv = nghttp3_stream_frq_emplace(conn->tx.ctrl, &fr); if (rv != 0) { nghttp3_mem_free(conn->mem, buf); diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c index 2efba7472c25..aea874fff4dd 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.c @@ -136,8 +136,8 @@ size_t nghttp3_frame_write_origin_len(uint64_t *ppayloadlen, int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, const nghttp3_mem *mem) { size_t i; - uint8_t *data = NULL; - size_t buflen = 0; + uint8_t *data; + size_t buflen; nghttp3_nv *p; if (nvlen == 0) { @@ -146,18 +146,32 @@ int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, return 0; } + if (sizeof(nghttp3_nv) > SIZE_MAX / nvlen) { + return NGHTTP3_ERR_INVALID_ARGUMENT; + } + + buflen = sizeof(nghttp3_nv) * nvlen; + for (i = 0; i < nvlen; ++i) { /* + 1 for null-termination */ if ((nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_NAME) == 0) { + if (nva[i].namelen == SIZE_MAX || + buflen > SIZE_MAX - nva[i].namelen - 1) { + return NGHTTP3_ERR_INVALID_ARGUMENT; + } + buflen += nva[i].namelen + 1; } if ((nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_VALUE) == 0) { + if (nva[i].valuelen == SIZE_MAX || + buflen > SIZE_MAX - nva[i].valuelen - 1) { + return NGHTTP3_ERR_INVALID_ARGUMENT; + } + buflen += nva[i].valuelen + 1; } } - buflen += sizeof(nghttp3_nv) * nvlen; - *pnva = nghttp3_mem_malloc(mem, buflen); if (*pnva == NULL) { @@ -169,30 +183,28 @@ int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, for (i = 0; i < nvlen; ++i) { p->flags = nva[i].flags; + p->namelen = nva[i].namelen; + p->valuelen = nva[i].valuelen; if (nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_NAME) { p->name = nva[i].name; - p->namelen = nva[i].namelen; } else { if (nva[i].namelen) { memcpy(data, nva[i].name, nva[i].namelen); nghttp3_downcase(data, nva[i].namelen); } p->name = data; - p->namelen = nva[i].namelen; data[p->namelen] = '\0'; data += nva[i].namelen + 1; } if (nva[i].flags & NGHTTP3_NV_FLAG_NO_COPY_VALUE) { p->value = nva[i].value; - p->valuelen = nva[i].valuelen; } else { if (nva[i].valuelen) { memcpy(data, nva[i].value, nva[i].valuelen); } p->value = data; - p->valuelen = nva[i].valuelen; data[p->valuelen] = '\0'; data += nva[i].valuelen + 1; } diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h index 7806cadbcf5f..fee30cb56d7d 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_frame.h @@ -247,6 +247,8 @@ size_t nghttp3_frame_write_origin_len(uint64_t *ppayloadlen, * * NGHTTP3_ERR_NOMEM * Out of memory. + * NGHTTP3_ERR_INVALID_ARGUMENT + * The required memory for |nva| of length |nvlen| is too large. */ int nghttp3_nva_copy(nghttp3_nv **pnva, const nghttp3_nv *nva, size_t nvlen, const nghttp3_mem *mem); diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_map.c b/deps/ngtcp2/nghttp3/lib/nghttp3_map.c index 7858d4cc3eb1..eae7c4d8dd40 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_map.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_map.c @@ -31,6 +31,7 @@ #include #include "nghttp3_conv.h" +#include "nghttp3_macro.h" #define NGHTTP3_INITIAL_HASHBITS 4 @@ -75,18 +76,19 @@ int nghttp3_map_each(const nghttp3_map *map, int (*func)(void *data, void *ptr), return 0; } -/* Hasher from - https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs - to maximize the output's sensitivity to all input bits. */ -#define NGHTTP3_MAP_HASHER 0xF1357AEA2E62A9C5ULL -/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get - the high bits with the good distribution. */ -#define NGHTTP3_MAP_FIBO 0x9E3779B97F4A7C15ULL +/* 64-bit finalizer (fmix64) from MurmurHash3 to maximize the output's + sensitivity to all input bits. */ +#define NGHTTP3_MAP_HASHER1 0xFF51AFD7ED558CCDULL +#define NGHTTP3_MAP_HASHER2 0xC4CEB9FE1A85EC53ULL static size_t map_index(const nghttp3_map *map, nghttp3_map_key_type key) { - key += map->seed; - key *= NGHTTP3_MAP_HASHER; - return (size_t)((key * NGHTTP3_MAP_FIBO) >> (64 - map->hashbits)); + key ^= map->seed; + key ^= key >> 33; + key *= NGHTTP3_MAP_HASHER1; + key ^= key >> 33; + key *= NGHTTP3_MAP_HASHER2; + key ^= key >> 33; + return (size_t)(key >> (64 - map->hashbits)); } #ifndef WIN32 @@ -108,17 +110,17 @@ void nghttp3_map_print_distance(const nghttp3_map *map) { } idx = map_index(map, map->keys[i]); - fprintf(stderr, "@%zu key=%" PRIu64 " base=%zu distance=%u\n", i, + fprintf(stderr, "@%zu key=%" PRIu64 " base=%zu distance=%zu\n", i, map->keys[i], idx, map->psl[i] - 1); } } #endif /* !defined(WIN32) */ static void map_set_entry(nghttp3_map *map, size_t idx, - nghttp3_map_key_type key, void *data, size_t psl) { + nghttp3_map_key_type key, size_t psl, void *data) { map->keys[idx] = key; + map->psl[idx] = psl; map->data[idx] = data; - map->psl[idx] = (uint8_t)psl; } #define NGHTTP3_SWAP(TYPE, A, B) \ @@ -130,15 +132,15 @@ static void map_set_entry(nghttp3_map *map, size_t idx, } while (0) /* - * map_insert inserts |key| and |data| to |map|, and returns the index - * where the pair is stored if it succeeds. Otherwise, it returns one - * of the following negative error codes: + * map_insert inserts |key| and |data| to |map|. + * + * It returns 0 if it succeeds, or one of the following negative error + * codes: * * NGHTTP3_ERR_INVALID_ARGUMENT * The another data associated to |key| is already present. */ -static nghttp3_ssize map_insert(nghttp3_map *map, nghttp3_map_key_type key, - void *data) { +static int map_insert(nghttp3_map *map, nghttp3_map_key_type key, void *data) { size_t idx = map_index(map, key); size_t mask = ((size_t)1 << map->hashbits) - 1; size_t psl = 1; @@ -148,16 +150,16 @@ static nghttp3_ssize map_insert(nghttp3_map *map, nghttp3_map_key_type key, kpsl = map->psl[idx]; if (kpsl == 0) { - map_set_entry(map, idx, key, data, psl); + map_set_entry(map, idx, key, psl, data); ++map->size; - return (nghttp3_ssize)idx; + return 0; } if (psl > kpsl) { NGHTTP3_SWAP(nghttp3_map_key_type, &key, &map->keys[idx]); + NGHTTP3_SWAP(size_t, &psl, &map->psl[idx]); NGHTTP3_SWAP(void *, &data, &map->data[idx]); - NGHTTP3_SWAP(uint8_t, &psl, &map->psl[idx]); } else if (map->keys[idx] == key) { /* This check ensures that no duplicate keys are inserted. But it is just a waste after first swap or if this function is @@ -179,14 +181,14 @@ static nghttp3_ssize map_insert(nghttp3_map *map, nghttp3_map_key_type key, static int map_resize(nghttp3_map *map, size_t new_hashbits) { size_t i; size_t tablelen; - nghttp3_ssize idx; nghttp3_map new_map = { .mem = map->mem, .seed = map->seed, .hashbits = new_hashbits, }; void *buf; - (void)idx; + int rv; + (void)rv; if (new_hashbits > NGHTTP3_MAP_MAX_HASHBITS) { return NGHTTP3_ERR_NOMEM; @@ -195,16 +197,16 @@ static int map_resize(nghttp3_map *map, size_t new_hashbits) { tablelen = (size_t)1 << new_hashbits; buf = nghttp3_mem_calloc(map->mem, tablelen, - sizeof(nghttp3_map_key_type) + sizeof(void *) + - sizeof(uint8_t)); - if (buf == NULL) { + sizeof(nghttp3_map_key_type) + sizeof(size_t) + + sizeof(void *)); + if (!buf) { return NGHTTP3_ERR_NOMEM; } new_map.keys = buf; - new_map.data = - (void *)((uint8_t *)new_map.keys + tablelen * sizeof(nghttp3_map_key_type)); - new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *); + new_map.psl = (size_t *)(void *)((uint8_t *)new_map.keys + + tablelen * sizeof(nghttp3_map_key_type)); + new_map.data = (void *)((uint8_t *)new_map.psl + tablelen * sizeof(size_t)); if (map->size) { tablelen = (size_t)1 << map->hashbits; @@ -214,31 +216,26 @@ static int map_resize(nghttp3_map *map, size_t new_hashbits) { continue; } - idx = map_insert(&new_map, map->keys[i], map->data[i]); + rv = map_insert(&new_map, map->keys[i], map->data[i]); /* map_insert must not fail because all keys are unique during resize. */ - assert(idx >= 0); + assert(0 == rv); } } nghttp3_mem_free(map->mem, map->keys); map->keys = new_map.keys; - map->data = new_map.data; map->psl = new_map.psl; + map->data = new_map.data; map->hashbits = new_hashbits; return 0; } -/* NGHTTP3_MAX_PSL_RESIZE_THRESH is the maximum psl threshold. If - reached, resize the table. */ -#define NGHTTP3_MAX_PSL_RESIZE_THRESH 128 - int nghttp3_map_insert(nghttp3_map *map, nghttp3_map_key_type key, void *data) { int rv; size_t tablelen; - nghttp3_ssize idx; assert(data); @@ -255,27 +252,9 @@ int nghttp3_map_insert(nghttp3_map *map, nghttp3_map_key_type key, void *data) { if (rv != 0) { return rv; } - - idx = map_insert(map, key, data); - if (idx < 0) { - return (int)idx; - } - - return 0; - } - - idx = map_insert(map, key, data); - if (idx < 0) { - return (int)idx; - } - - /* Resize if psl reaches really large value which is almost - improbable, but just in case. */ - if (map->psl[idx] - 1 < NGHTTP3_MAX_PSL_RESIZE_THRESH) { - return 0; } - return map_resize(map, map->hashbits + 1); + return map_insert(map, key, data); } void *nghttp3_map_find(const nghttp3_map *map, nghttp3_map_key_type key) { @@ -333,7 +312,7 @@ int nghttp3_map_remove(nghttp3_map *map, nghttp3_map_key_type key) { break; } - map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1); + map_set_entry(map, dest, map->keys[idx], kpsl - 1, map->data[idx]); dest = idx; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_map.h b/deps/ngtcp2/nghttp3/lib/nghttp3_map.h index 337f3d63114c..89867fd05468 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_map.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_map.h @@ -41,11 +41,11 @@ typedef uint64_t nghttp3_map_key_type; typedef struct nghttp3_map { nghttp3_map_key_type *keys; - void **data; /* psl is the Probe Sequence Length. 0 has special meaning that the element is not stored at i-th position if psl[i] == 0. Because of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */ - uint8_t *psl; + size_t *psl; + void **data; const nghttp3_mem *mem; uint64_t seed; size_t size; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c b/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c index 8e950a201d89..2e3d063e1381 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_qpack.c @@ -2568,24 +2568,23 @@ nghttp3_ssize nghttp3_qpack_encoder_read_decoder(nghttp3_qpack_encoder *encoder, for (; p != end;) { switch (encoder->state) { case NGHTTP3_QPACK_DS_STATE_OPCODE: - switch ((*p) & 0xC0U) { - case 0x80U: - case 0xC0U: - DEBUGF("qpack::encode: OPCODE_SECTION_ACK\n"); - encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK; - encoder->rstate.prefix = 7; + switch ((*p) >> 6) { + case 0x0U: + DEBUGF("qpack::encode: OPCODE_ICNT_INCREMENT\n"); + encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT; + encoder->rstate.prefix = 6; break; - case 0x40U: + case 0x1U: DEBUGF("qpack::encode: OPCODE_STREAM_CANCEL\n"); encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_STREAM_CANCEL; encoder->rstate.prefix = 6; break; default: - DEBUGF("qpack::encode: OPCODE_ICNT_INCREMENT\n"); - encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_ICNT_INCREMENT; - encoder->rstate.prefix = 6; + DEBUGF("qpack::encode: OPCODE_SECTION_ACK\n"); + encoder->opcode = NGHTTP3_QPACK_DS_OPCODE_SECTION_ACK; + encoder->rstate.prefix = 7; } encoder->state = NGHTTP3_QPACK_DS_STATE_READ_NUMBER; /* fall through */ @@ -2842,39 +2841,36 @@ nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder, busy = 0; switch (decoder->state) { case NGHTTP3_QPACK_ES_STATE_OPCODE: - switch ((*p) & 0xE0U) { - case 0x80U: - case 0xA0U: - case 0xC0U: - case 0xE0U: - DEBUGF("qpack::decode: OPCODE_INSERT_INDEXED\n"); - decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED; - decoder->rstate.dynamic = !((*p) & 0x40U); - decoder->rstate.prefix = 6; + switch ((*p) >> 5) { + case 0x0U: + DEBUGF("qpack::decode: OPCODE_DUPLICATE\n"); + decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_DUPLICATE; + decoder->rstate.dynamic = 1; + decoder->rstate.prefix = 5; decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX; break; - case 0x40U: - case 0x60U: + case 0x1U: + DEBUGF("qpack::decode: OPCODE_SET_DTABLE_TABLE_CAP\n"); + decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP; + decoder->rstate.prefix = 5; + decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX; + + break; + case 0x2U: + case 0x3U: DEBUGF("qpack::decode: OPCODE_INSERT\n"); decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT; decoder->rstate.dynamic = 0; decoder->rstate.prefix = 5; decoder->state = NGHTTP3_QPACK_ES_STATE_CHECK_NAME_HUFFMAN; - break; - case 0x20U: - DEBUGF("qpack::decode: OPCODE_SET_DTABLE_TABLE_CAP\n"); - decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP; - decoder->rstate.prefix = 5; - decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX; - break; default: - DEBUGF("qpack::decode: OPCODE_DUPLICATE\n"); - decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_DUPLICATE; - decoder->rstate.dynamic = 1; - decoder->rstate.prefix = 5; + DEBUGF("qpack::decode: OPCODE_INSERT_INDEXED\n"); + decoder->opcode = NGHTTP3_QPACK_ES_OPCODE_INSERT_INDEXED; + decoder->rstate.dynamic = !((*p) & 0x40U); + decoder->rstate.prefix = 6; decoder->state = NGHTTP3_QPACK_ES_STATE_READ_INDEX; } break; @@ -2895,6 +2891,12 @@ nghttp3_ssize nghttp3_qpack_decoder_read_encoder(nghttp3_qpack_decoder *decoder, if (decoder->opcode == NGHTTP3_QPACK_ES_OPCODE_SET_DTABLE_CAP) { DEBUGF("qpack::decode: Set dtable capacity to %" PRIu64 "\n", decoder->rstate.left); +#if SIZE_MAX < UINT64_MAX + if (decoder->rstate.left > SIZE_MAX) { + return NGHTTP3_ERR_QPACK_ENCODER_STREAM_ERROR; + } +#endif /* SIZE_MAX < UINT64_MAX */ + rv = nghttp3_qpack_decoder_set_max_dtable_capacity( decoder, (size_t)decoder->rstate.left); if (rv != 0) { @@ -3433,36 +3435,26 @@ nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder, case NGHTTP3_QPACK_RS_STATE_OPCODE: assert(sctx->rstate.left == 0); assert(sctx->rstate.shift == 0); - switch ((*p) & 0xF0U) { - case 0x80U: - case 0x90U: - case 0xA0U: - case 0xB0U: - case 0xC0U: - case 0xD0U: - case 0xE0U: - case 0xF0U: - DEBUGF("qpack::decode: OPCODE_INDEXED\n"); - sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED; - sctx->rstate.dynamic = !((*p) & 0x40U); - sctx->rstate.prefix = 6; + switch ((*p) >> 4) { + case 0x0U: + DEBUGF("qpack::decode: OPCODE_INDEXED_NAME_PB\n"); + sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB; + sctx->rstate.never = (*p) & 0x08U; + sctx->rstate.dynamic = 1; + sctx->rstate.prefix = 3; sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX; break; - case 0x40U: - case 0x50U: - case 0x60U: - case 0x70U: - DEBUGF("qpack::decode: OPCODE_INDEXED_NAME\n"); - sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME; - sctx->rstate.never = (*p) & 0x20U; - sctx->rstate.dynamic = !((*p) & 0x10U); + case 0x1U: + DEBUGF("qpack::decode: OPCODE_INDEXED_PB\n"); + sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB; + sctx->rstate.dynamic = 1; sctx->rstate.prefix = 4; sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX; break; - case 0x20U: - case 0x30U: + case 0x2U: + case 0x3U: DEBUGF("qpack::decode: OPCODE_LITERAL\n"); sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_LITERAL; sctx->rstate.never = (*p) & 0x10U; @@ -3471,20 +3463,23 @@ nghttp3_qpack_decoder_read_request(nghttp3_qpack_decoder *decoder, sctx->state = NGHTTP3_QPACK_RS_STATE_CHECK_NAME_HUFFMAN; break; - case 0x10U: - DEBUGF("qpack::decode: OPCODE_INDEXED_PB\n"); - sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_PB; - sctx->rstate.dynamic = 1; + case 0x4U: + case 0x5U: + case 0x6U: + case 0x7U: + DEBUGF("qpack::decode: OPCODE_INDEXED_NAME\n"); + sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME; + sctx->rstate.never = (*p) & 0x20U; + sctx->rstate.dynamic = !((*p) & 0x10U); sctx->rstate.prefix = 4; sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX; break; default: - DEBUGF("qpack::decode: OPCODE_INDEXED_NAME_PB\n"); - sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED_NAME_PB; - sctx->rstate.never = (*p) & 0x08U; - sctx->rstate.dynamic = 1; - sctx->rstate.prefix = 3; + DEBUGF("qpack::decode: OPCODE_INDEXED\n"); + sctx->opcode = NGHTTP3_QPACK_RS_OPCODE_INDEXED; + sctx->rstate.dynamic = !((*p) & 0x40U); + sctx->rstate.prefix = 6; sctx->state = NGHTTP3_QPACK_RS_STATE_READ_INDEX; } break; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.c b/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.c index d7a0267530ca..d6d0738e5de6 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.c +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.c @@ -32,6 +32,8 @@ void nghttp3_ratelim_init(nghttp3_ratelim *rlim, uint64_t burst, uint64_t rate, nghttp3_tstamp ts) { + burst = nghttp3_min(burst, NGHTTP3_RATELIM_MAX_BURST); + *rlim = (nghttp3_ratelim){ .burst = burst, .rate = rate, @@ -53,19 +55,16 @@ static void ratelim_update(nghttp3_ratelim *rlim, nghttp3_tstamp ts) { d = ts - rlim->ts; rlim->ts = ts; - if (rlim->rate > (UINT64_MAX - rlim->carry) / d) { - gain = UINT64_MAX; - } else { + if (rlim->rate <= (UINT64_MAX - rlim->carry) / d) { gain = rlim->rate * d + rlim->carry; - } + gps = gain / NGHTTP3_SECONDS; - gps = gain / NGHTTP3_SECONDS; + if (gps < rlim->burst && rlim->tokens < rlim->burst - gps) { + rlim->tokens += gps; + rlim->carry = gain % NGHTTP3_SECONDS; - if (gps < rlim->burst && rlim->tokens < rlim->burst - gps) { - rlim->tokens += gps; - rlim->carry = gain % NGHTTP3_SECONDS; - - return; + return; + } } rlim->tokens = rlim->burst; diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.h b/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.h index 68aab93a61bf..ba8f53788146 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_ratelim.h @@ -33,6 +33,9 @@ #include +/* NGHTTP3_RATELIM_MAX_BURST is the maximum value of the burst. */ +#define NGHTTP3_RATELIM_MAX_BURST (UINT64_MAX / NGHTTP3_SECONDS) + typedef struct nghttp3_ratelim { /* burst is the maximum number of tokens. */ uint64_t burst; @@ -48,8 +51,8 @@ typedef struct nghttp3_ratelim { nghttp3_tstamp ts; } nghttp3_ratelim; -/* nghttp3_ratelim_init initializes |rlim| with the given - parameters. */ +/* nghttp3_ratelim_init initializes |rlim| with the given parameters. + |burst| is clamped to NGHTTP3_RATELIM_MAX_BURST. */ void nghttp3_ratelim_init(nghttp3_ratelim *rlim, uint64_t burst, uint64_t rate, nghttp3_tstamp ts); diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h index d313b1c192b9..07d71573a58f 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_stream.h @@ -42,8 +42,9 @@ #define NGHTTP3_STREAM_MIN_CHUNK_SIZE 256 /* NGHTTP3_MIN_UNSENT_BYTES is the minimum unsent bytes which is large - enough to fill outgoing single QUIC packet. */ -#define NGHTTP3_MIN_UNSENT_BYTES 4096 + enough to fill outgoing single QUIC packet or TLS record in case of + QMux (Cut 2 bytes for QMux record length). */ +#define NGHTTP3_MIN_UNSENT_BYTES 16382 /* NGHTTP3_STREAM_MIN_WRITELEN is the minimum length of write to cause the stream to reschedule. */ diff --git a/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h index c609d7ed72f3..362ceb08c3d2 100644 --- a/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h +++ b/deps/ngtcp2/nghttp3/lib/nghttp3_unreachable.h @@ -44,10 +44,10 @@ #ifdef _MSC_VER __declspec(noreturn) #endif /* defined(_MSC_VER) */ - void nghttp3_unreachable_fail(const char *file, int line, const char *func) +void nghttp3_unreachable_fail(const char *file, int line, const char *func) #ifndef _MSC_VER - __attribute__((noreturn)) + __attribute__((noreturn)) #endif /* !defined(_MSC_VER) */ - ; + ; #endif /* !defined(NGHTTP3_UNREACHABLE_H) */