mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
h2: tolerate unexpected server behaviour
Make sure we only do one SETTINGS ack handling Fix corner case of ignored header with 0 data being the last in the HEADERS
This commit is contained in:
parent
300e22c815
commit
da8995bb61
4 changed files with 41 additions and 20 deletions
|
@ -746,6 +746,7 @@ struct lws {
|
|||
unsigned int client_pipeline:1;
|
||||
unsigned int client_h2_alpn:1;
|
||||
unsigned int client_h2_substream:1;
|
||||
unsigned int client_h2_migrated:1;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -396,7 +396,7 @@ lws_token_from_index(struct lws *wsi, int index, const char **arg, int *len,
|
|||
|
||||
if (index >= (int)LWS_ARRAY_SIZE(static_token) + dyn->used_entries) {
|
||||
lwsl_info(" %s: adjusted index %d >= %d\n", __func__, index,
|
||||
dyn->used_entries);
|
||||
(int)LWS_ARRAY_SIZE(static_token) + dyn->used_entries);
|
||||
lws_h2_goaway(wsi, H2_ERR_COMPRESSION_ERROR,
|
||||
"index out of range");
|
||||
return -1;
|
||||
|
@ -1002,6 +1002,13 @@ int lws_hpack_interpret(struct lws *wsi, unsigned char c)
|
|||
h2n->hpack = HPKS_HLEN_EXT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (h2n->value && !h2n->hpack_len) {
|
||||
lwsl_debug("%s: zero-length header data\n", __func__);
|
||||
h2n->hpack = HPKS_TYPE;
|
||||
goto fin;
|
||||
}
|
||||
|
||||
pre_data:
|
||||
h2n->hpack = HPKS_DATA;
|
||||
if (!h2n->value || !h2n->hdr_idx) {
|
||||
|
@ -1179,7 +1186,7 @@ swallow:
|
|||
"Huffman padding excessive or wrong");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fin:
|
||||
if (!h2n->value && (
|
||||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE ||
|
||||
h2n->hpack_type == HPKT_LITERAL_HDR_VALUE_INCR ||
|
||||
|
|
|
@ -166,7 +166,8 @@ lws_wsi_server_new(struct lws_vhost *vh, struct lws *parent_wsi,
|
|||
* connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||
*/
|
||||
if (sid <= h2n->highest_sid_opened) {
|
||||
lwsl_info("%s: tried to open lower sid %d\n", __func__, sid);
|
||||
lwsl_info("%s: tried to open lower sid %d (%d)\n", __func__,
|
||||
sid, h2n->highest_sid_opened);
|
||||
lws_h2_goaway(nwsi, H2_ERR_PROTOCOL_ERROR, "Bad sid");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1306,7 +1307,7 @@ lws_h2_parse_end_of_frame(struct lws *wsi)
|
|||
case LWS_H2_FRAME_TYPE_SETTINGS:
|
||||
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
if (wsi->client_h2_alpn &&
|
||||
if (wsi->client_h2_alpn && !wsi->client_h2_migrated &&
|
||||
!(h2n->flags & LWS_H2_FLAG_SETTINGS_ACK)) {
|
||||
struct lws_h2_protocol_send *pps;
|
||||
|
||||
|
@ -1314,7 +1315,8 @@ lws_h2_parse_end_of_frame(struct lws *wsi)
|
|||
#if defined(LWS_WITH_FILE_OPS)
|
||||
wsi->http.fop_fd = NULL;
|
||||
#endif
|
||||
|
||||
lwsl_info("%s: migrating\n", __func__);
|
||||
wsi->client_h2_migrated = 1;
|
||||
/*
|
||||
* we need to treat the headers from the upgrade as the
|
||||
* first job. So these need to get shifted to sid 1.
|
||||
|
|
|
@ -1078,13 +1078,14 @@ swallow:
|
|||
c += 'a' - 'A';
|
||||
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
|
||||
/*
|
||||
* ...in case it's an unknown header, speculatively
|
||||
* store it as the name comes in. If we recognize it as
|
||||
* a known header, we'll snip this.
|
||||
*/
|
||||
|
||||
if (!ah->unk_pos) {
|
||||
if (!wsi->http2_substream && !ah->unk_pos) {
|
||||
ah->unk_pos = ah->pos;
|
||||
/*
|
||||
* Prepare new unknown header linked-list entry
|
||||
|
@ -1106,7 +1107,7 @@ swallow:
|
|||
pos = ah->lextable_pos;
|
||||
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
if (pos < 0 && c == ':') {
|
||||
if (!wsi->http2_substream && pos < 0 && c == ':') {
|
||||
/*
|
||||
* process unknown headers
|
||||
*
|
||||
|
@ -1170,13 +1171,16 @@ nope:
|
|||
/* b7 = 0, end or 3-byte */
|
||||
if (lextable[pos] < FAIL_CHAR) {
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
/*
|
||||
* We hit a terminal marker, so we
|
||||
* recognized this header... drop the
|
||||
* speculative name part storage
|
||||
*/
|
||||
ah->pos = ah->unk_pos;
|
||||
ah->unk_pos = 0;
|
||||
if (!wsi->http2_substream) {
|
||||
/*
|
||||
* We hit a terminal marker, so
|
||||
* we recognized this header...
|
||||
* drop the speculative name
|
||||
* part storage
|
||||
*/
|
||||
ah->pos = ah->unk_pos;
|
||||
ah->unk_pos = 0;
|
||||
}
|
||||
#endif
|
||||
ah->lextable_pos = pos;
|
||||
break;
|
||||
|
@ -1213,19 +1217,25 @@ nope:
|
|||
#if !defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
ah->parser_state = WSI_TOKEN_SKIPPING;
|
||||
#endif
|
||||
if (wsi->http2_substream)
|
||||
ah->parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m != LWS_ARRAY_SIZE(methods))
|
||||
if (m != LWS_ARRAY_SIZE(methods)) {
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
/*
|
||||
* We have the method, this is just an
|
||||
* unknown header then
|
||||
*/
|
||||
goto unknown_hdr;
|
||||
if (!wsi->http2_substream)
|
||||
goto unknown_hdr;
|
||||
else
|
||||
break;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* ...it's an unknown http method from a client
|
||||
* in fact, it cannot be valid http.
|
||||
|
@ -1246,15 +1256,15 @@ nope:
|
|||
}
|
||||
if (ah->lextable_pos < 0) {
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
goto unknown_hdr;
|
||||
#else
|
||||
if (!wsi->http2_substream)
|
||||
goto unknown_hdr;
|
||||
#endif
|
||||
/*
|
||||
* ...otherwise for a client, let him ignore
|
||||
* unknown headers coming from the server
|
||||
*/
|
||||
ah->parser_state = WSI_TOKEN_SKIPPING;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (lextable[ah->lextable_pos] < FAIL_CHAR) {
|
||||
|
@ -1301,7 +1311,8 @@ nope:
|
|||
unknown_hdr:
|
||||
//ah->parser_state = WSI_TOKEN_SKIPPING;
|
||||
//break;
|
||||
break;
|
||||
if (!wsi->http2_substream)
|
||||
break;
|
||||
#endif
|
||||
|
||||
start_fragment:
|
||||
|
|
Loading…
Add table
Reference in a new issue