Pass unknown SETTINGS values to nghttp2_on_frame_recv_callback
This commit is contained in:
parent
d88f962565
commit
40f3779eb1
|
@ -463,25 +463,11 @@ size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
|||
return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv, nghttp2_mem *mem) {
|
||||
size_t payloadlen = niv * sizeof(nghttp2_settings_entry);
|
||||
|
||||
if (niv == 0) {
|
||||
frame->iv = NULL;
|
||||
} else {
|
||||
frame->iv = nghttp2_mem_malloc(mem, payloadlen);
|
||||
|
||||
if (frame->iv == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
memcpy(frame->iv, iv, payloadlen);
|
||||
}
|
||||
|
||||
size_t niv) {
|
||||
frame->iv = iv;
|
||||
frame->niv = niv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
||||
|
|
|
@ -215,18 +215,12 @@ void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
|||
const uint8_t *payload);
|
||||
|
||||
/*
|
||||
* Makes a copy of |iv| in frame->settings.iv. The |niv| is assigned
|
||||
* to frame->settings.niv.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* Initializes payload of frame->settings. The |frame| takes
|
||||
* ownership of |iv|.
|
||||
*/
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv, nghttp2_mem *mem);
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
|
||||
|
|
|
@ -305,6 +305,13 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
|
|||
break;
|
||||
case NGHTTP2_SETTINGS:
|
||||
nghttp2_frame_settings_free(&iframe->frame.settings, mem);
|
||||
|
||||
nghttp2_mem_free(mem, iframe->iv);
|
||||
|
||||
iframe->iv = NULL;
|
||||
iframe->niv = 0;
|
||||
iframe->max_niv = 0;
|
||||
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
nghttp2_frame_push_promise_free(&iframe->frame.push_promise, mem);
|
||||
|
@ -351,12 +358,8 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
|
|||
|
||||
iframe->raw_lbuf = NULL;
|
||||
|
||||
iframe->niv = 0;
|
||||
iframe->payloadleft = 0;
|
||||
iframe->padlen = 0;
|
||||
iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].settings_id =
|
||||
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||
iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].value = UINT32_MAX;
|
||||
}
|
||||
|
||||
static void init_settings(nghttp2_settings_storage *settings) {
|
||||
|
@ -4365,15 +4368,13 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
|
|||
}
|
||||
|
||||
static int session_process_settings_frame(nghttp2_session *session) {
|
||||
int rv;
|
||||
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||
nghttp2_frame *frame = &iframe->frame;
|
||||
size_t i;
|
||||
nghttp2_settings_entry min_header_size_entry;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = &session->mem;
|
||||
min_header_size_entry = iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1];
|
||||
if (iframe->max_niv) {
|
||||
min_header_size_entry = iframe->iv[iframe->max_niv - 1];
|
||||
|
||||
if (min_header_size_entry.value < UINT32_MAX) {
|
||||
/* If we have less value, then we must have
|
||||
|
@ -4391,13 +4392,15 @@ static int session_process_settings_frame(nghttp2_session *session) {
|
|||
iframe->iv[i] = min_header_size_entry;
|
||||
}
|
||||
}
|
||||
|
||||
rv = nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv,
|
||||
iframe->niv, mem);
|
||||
if (rv != 0) {
|
||||
assert(nghttp2_is_fatal(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv,
|
||||
iframe->niv);
|
||||
|
||||
iframe->iv = NULL;
|
||||
iframe->niv = 0;
|
||||
iframe->max_niv = 0;
|
||||
|
||||
return nghttp2_session_on_settings_received(session, frame, 0 /* ACK */);
|
||||
}
|
||||
|
||||
|
@ -5053,6 +5056,7 @@ static size_t inbound_frame_buf_read(nghttp2_inbound_frame *iframe,
|
|||
*/
|
||||
static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
|
||||
nghttp2_settings_entry iv;
|
||||
nghttp2_settings_entry *min_header_table_size_entry;
|
||||
size_t i;
|
||||
|
||||
nghttp2_frame_unpack_settings_entry(&iv, iframe->sbuf.pos);
|
||||
|
@ -5066,8 +5070,11 @@ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
|
|||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||
break;
|
||||
default:
|
||||
DEBUGF(fprintf(stderr, "recv: ignore unknown settings id=0x%02x\n",
|
||||
iv.settings_id));
|
||||
DEBUGF(
|
||||
fprintf(stderr, "recv: unknown settings id=0x%02x\n", iv.settings_id));
|
||||
|
||||
iframe->iv[iframe->niv++] = iv;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5082,10 +5089,13 @@ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
|
|||
iframe->iv[iframe->niv++] = iv;
|
||||
}
|
||||
|
||||
if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE &&
|
||||
iv.value < iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1].value) {
|
||||
if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) {
|
||||
/* Keep track of minimum value of SETTINGS_HEADER_TABLE_SIZE */
|
||||
min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
|
||||
|
||||
iframe->iv[NGHTTP2_INBOUND_NUM_IV - 1] = iv;
|
||||
if (iv.value < min_header_table_size_entry->value) {
|
||||
min_header_table_size_entry->value = iv.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5458,6 +5468,25 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||
iframe->state = NGHTTP2_IB_READ_SETTINGS;
|
||||
|
||||
if (iframe->payloadleft) {
|
||||
nghttp2_settings_entry *min_header_table_size_entry;
|
||||
|
||||
/* We allocate iv with addtional one entry, to store the
|
||||
minimum header table size. */
|
||||
iframe->max_niv =
|
||||
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
|
||||
|
||||
iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
|
||||
iframe->max_niv);
|
||||
|
||||
if (!iframe->iv) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
|
||||
min_header_table_size_entry->settings_id =
|
||||
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||
min_header_table_size_entry->value = UINT32_MAX;
|
||||
|
||||
inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -120,18 +120,16 @@ typedef enum {
|
|||
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
|
||||
} nghttp2_inbound_state;
|
||||
|
||||
#define NGHTTP2_INBOUND_NUM_IV 7
|
||||
|
||||
typedef struct {
|
||||
nghttp2_frame frame;
|
||||
/* Storage for extension frame payload. frame->ext.payload points
|
||||
to this structure to avoid frequent memory allocation. */
|
||||
nghttp2_ext_frame_payload ext_frame_payload;
|
||||
/* The received SETTINGS entry. The protocol says that we only cares
|
||||
about the defined settings ID. If unknown ID is received, it is
|
||||
ignored. We use last entry to hold minimum header table size if
|
||||
same settings are multiple times. */
|
||||
nghttp2_settings_entry iv[NGHTTP2_INBOUND_NUM_IV];
|
||||
/* The received SETTINGS entry. For the standard settings entries,
|
||||
we only keep the last seen value. For
|
||||
SETTINGS_HEADER_TABLE_SIZE, we also keep minimum value in the
|
||||
last index. */
|
||||
nghttp2_settings_entry *iv;
|
||||
/* buffer pointers to small buffer, raw_sbuf */
|
||||
nghttp2_buf sbuf;
|
||||
/* buffer pointers to large buffer, raw_lbuf */
|
||||
|
@ -140,6 +138,8 @@ typedef struct {
|
|||
uint8_t *raw_lbuf;
|
||||
/* The number of entry filled in |iv| */
|
||||
size_t niv;
|
||||
/* The number of entries |iv| can store. */
|
||||
size_t max_niv;
|
||||
/* How many bytes we still need to receive for current frame */
|
||||
size_t payloadleft;
|
||||
/* padding length for the current frame */
|
||||
|
|
Loading…
Reference in New Issue