Handle limitations on where dynamic table size updates can be placed

pull/4267/head
Craig Tiller 9 years ago
parent 9fac2afdaf
commit 7b01b754ce
  1. 21
      src/core/transport/chttp2/hpack_parser.c
  2. 2
      src/core/transport/chttp2/hpack_parser.h

@ -728,6 +728,7 @@ static int finish_indexed_field(grpc_chttp2_hpack_parser *p,
/* parse an indexed field with index < 127 */ /* parse an indexed field with index < 127 */
static int parse_indexed_field(grpc_chttp2_hpack_parser *p, static int parse_indexed_field(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
p->dynamic_table_update_allowed = 0;
p->index = (*cur) & 0x7f; p->index = (*cur) & 0x7f;
return finish_indexed_field(p, cur + 1, end); return finish_indexed_field(p, cur + 1, end);
} }
@ -737,6 +738,7 @@ static int parse_indexed_field_x(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
finish_indexed_field}; finish_indexed_field};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = 0x7f; p->index = 0x7f;
p->parsing.value = &p->index; p->parsing.value = &p->index;
@ -768,6 +770,7 @@ static int parse_lithdr_incidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_incidx}; parse_value_string_with_indexed_key, finish_lithdr_incidx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = (*cur) & 0x3f; p->index = (*cur) & 0x3f;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
@ -779,6 +782,7 @@ static int parse_lithdr_incidx_x(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key, parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_incidx}; finish_lithdr_incidx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = 0x3f; p->index = 0x3f;
p->parsing.value = &p->index; p->parsing.value = &p->index;
@ -791,6 +795,7 @@ static int parse_lithdr_incidx_v(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix, parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_incidx_v}; parse_value_string_with_literal_key, finish_lithdr_incidx_v};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
} }
@ -819,6 +824,7 @@ static int parse_lithdr_notidx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_notidx}; parse_value_string_with_indexed_key, finish_lithdr_notidx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = (*cur) & 0xf; p->index = (*cur) & 0xf;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
@ -830,6 +836,7 @@ static int parse_lithdr_notidx_x(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key, parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_notidx}; finish_lithdr_notidx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = 0xf; p->index = 0xf;
p->parsing.value = &p->index; p->parsing.value = &p->index;
@ -842,6 +849,7 @@ static int parse_lithdr_notidx_v(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix, parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_notidx_v}; parse_value_string_with_literal_key, finish_lithdr_notidx_v};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
} }
@ -870,6 +878,7 @@ static int parse_lithdr_nvridx(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_value_string_with_indexed_key, finish_lithdr_nvridx}; parse_value_string_with_indexed_key, finish_lithdr_nvridx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = (*cur) & 0xf; p->index = (*cur) & 0xf;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
@ -881,6 +890,7 @@ static int parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_string_prefix, parse_value_string_with_indexed_key, parse_string_prefix, parse_value_string_with_indexed_key,
finish_lithdr_nvridx}; finish_lithdr_nvridx};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
p->index = 0xf; p->index = 0xf;
p->parsing.value = &p->index; p->parsing.value = &p->index;
@ -893,6 +903,7 @@ static int parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser *p,
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
parse_key_string, parse_string_prefix, parse_key_string, parse_string_prefix,
parse_value_string_with_literal_key, finish_lithdr_nvridx_v}; parse_value_string_with_literal_key, finish_lithdr_nvridx_v};
p->dynamic_table_update_allowed = 0;
p->next_state = and_then; p->next_state = and_then;
return parse_string_prefix(p, cur + 1, end); return parse_string_prefix(p, cur + 1, end);
} }
@ -908,6 +919,10 @@ static int finish_max_tbl_size(grpc_chttp2_hpack_parser *p,
/* parse a max table size change, max size < 15 */ /* parse a max table size change, max size < 15 */
static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur, static int parse_max_tbl_size(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
const gpr_uint8 *end) { const gpr_uint8 *end) {
if (p->dynamic_table_update_allowed == 0) {
return 0;
}
p->dynamic_table_update_allowed--;
p->index = (*cur) & 0x1f; p->index = (*cur) & 0x1f;
return finish_max_tbl_size(p, cur + 1, end); return finish_max_tbl_size(p, cur + 1, end);
} }
@ -917,6 +932,10 @@ static int parse_max_tbl_size_x(grpc_chttp2_hpack_parser *p,
const gpr_uint8 *cur, const gpr_uint8 *end) { const gpr_uint8 *cur, const gpr_uint8 *end) {
static const grpc_chttp2_hpack_parser_state and_then[] = { static const grpc_chttp2_hpack_parser_state and_then[] = {
finish_max_tbl_size}; finish_max_tbl_size};
if (p->dynamic_table_update_allowed == 0) {
return 0;
}
p->dynamic_table_update_allowed--;
p->next_state = and_then; p->next_state = and_then;
p->index = 0x1f; p->index = 0x1f;
p->parsing.value = &p->index; p->parsing.value = &p->index;
@ -1359,6 +1378,7 @@ void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p) {
p->value.str = NULL; p->value.str = NULL;
p->value.capacity = 0; p->value.capacity = 0;
p->value.length = 0; p->value.length = 0;
p->dynamic_table_update_allowed = 2;
grpc_chttp2_hptbl_init(&p->table); grpc_chttp2_hptbl_init(&p->table);
} }
@ -1414,6 +1434,7 @@ grpc_chttp2_parse_error grpc_chttp2_header_parser_parse(
parser->on_header_user_data = NULL; parser->on_header_user_data = NULL;
parser->is_boundary = 0xde; parser->is_boundary = 0xde;
parser->is_eof = 0xde; parser->is_eof = 0xde;
parser->dynamic_table_update_allowed = 2;
} }
GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0); GPR_TIMER_END("grpc_chttp2_hpack_parser_parse", 0);
return GRPC_CHTTP2_PARSE_OK; return GRPC_CHTTP2_PARSE_OK;

@ -85,6 +85,8 @@ struct grpc_chttp2_hpack_parser {
gpr_uint8 binary; gpr_uint8 binary;
/* is the current string huffman encoded? */ /* is the current string huffman encoded? */
gpr_uint8 huff; gpr_uint8 huff;
/* is a dynamic table update allowed? */
gpr_uint8 dynamic_table_update_allowed;
/* set by higher layers, used by grpc_chttp2_header_parser_parse to signal /* set by higher layers, used by grpc_chttp2_header_parser_parse to signal
it should append a metadata boundary at the end of frame */ it should append a metadata boundary at the end of frame */
gpr_uint8 is_boundary; gpr_uint8 is_boundary;

Loading…
Cancel
Save