1
0
Fork 0
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:
Andy Green 2019-10-10 16:37:38 +01:00
parent 300e22c815
commit da8995bb61
4 changed files with 41 additions and 20 deletions

View file

@ -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

View file

@ -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 ||

View file

@ -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.

View file

@ -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: