diff options
author | Craig Tiller <ctiller@google.com> | 2015-05-08 09:41:16 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2015-05-08 09:41:16 -0700 |
commit | a7af3f8854e132e32d2417bec9d5de1cb4646d72 (patch) | |
tree | 171b44f1ec2777334dd1ac000abeb7c10af2e3c5 /src/core | |
parent | 0a2bb1d9d6e41ca7e911523baaf4dfb7973487b2 (diff) | |
parent | 72a96463f689748c7b63c9f39f92d33e87e87315 (diff) |
Merge github.com:grpc/grpc into we-dont-need-no-backup
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/surface/call.c | 41 | ||||
-rw-r--r-- | src/core/transport/chttp2_transport.c | 6 | ||||
-rw-r--r-- | src/core/transport/metadata.c | 16 | ||||
-rw-r--r-- | src/core/transport/metadata.h | 3 |
4 files changed, 56 insertions, 10 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 7ab9142947..f3658b56c4 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -711,6 +711,10 @@ static void call_on_done_recv(void *pc, int success) { break; } } + if (!success) { + grpc_stream_ops_unref_owned_objects(&call->recv_ops.ops[i], + call->recv_ops.nops - i); + } if (call->recv_state == GRPC_STREAM_RECV_CLOSED) { GPR_ASSERT(call->read_state <= READ_STATE_READ_CLOSED); call->read_state = READ_STATE_READ_CLOSED; @@ -739,14 +743,9 @@ static void call_on_done_recv(void *pc, int success) { GRPC_TIMER_BEGIN(GRPC_PTAG_CALL_ON_DONE_RECV, 0); } -static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count, - grpc_metadata *metadata) { +static int prepare_application_metadata(grpc_call *call, size_t count, + grpc_metadata *metadata) { size_t i; - grpc_mdelem_list out; - if (count == 0) { - out.head = out.tail = NULL; - return out; - } for (i = 0; i < count; i++) { grpc_metadata *md = &metadata[i]; grpc_metadata *next_md = (i == count - 1) ? NULL : &metadata[i + 1]; @@ -756,9 +755,27 @@ static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count, l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length); + if (!grpc_mdstr_is_legal_header(l->md->key)) { + gpr_log(GPR_ERROR, "attempt to send invalid metadata key"); + return 0; + } else if (!grpc_mdstr_is_bin_suffixed(l->md->key) && + !grpc_mdstr_is_legal_header(l->md->value)) { + gpr_log(GPR_ERROR, "attempt to send invalid metadata value"); + return 0; + } l->next = next_md ? (grpc_linked_mdelem *)&next_md->internal_data : NULL; l->prev = prev_md ? (grpc_linked_mdelem *)&prev_md->internal_data : NULL; } + return 1; +} + +static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count, + grpc_metadata *metadata) { + grpc_mdelem_list out; + if (count == 0) { + out.head = out.tail = NULL; + return out; + } out.head = (grpc_linked_mdelem *)&(metadata[0].internal_data); out.tail = (grpc_linked_mdelem *)&(metadata[count - 1].internal_data); return out; @@ -954,8 +971,16 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } else if (call->request_set[op] == REQSET_DONE) { return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED); } - have_ops |= 1u << op; data = reqs[i].data; + if (op == GRPC_IOREQ_SEND_INITIAL_METADATA || + op == GRPC_IOREQ_SEND_TRAILING_METADATA) { + if (!prepare_application_metadata(call, data.send_metadata.count, + data.send_metadata.metadata)) { + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_INVALID_METADATA); + } + } + have_ops |= 1u << op; call->request_data[op] = data; call->request_set[op] = set; diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index ea24796f35..a6f9f782a1 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1927,8 +1927,10 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, break; case GRPC_ENDPOINT_CB_OK: lock(t); - for (i = 0; i < nslices && process_read(t, slices[i]); i++) - ; + if (t->cb) { + for (i = 0; i < nslices && process_read(t, slices[i]); i++) + ; + } unlock(t); keep_reading = 1; break; diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index 74e94b2c24..c80d67823f 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -569,3 +569,19 @@ void grpc_mdctx_locked_mdelem_unref(grpc_mdctx *ctx, grpc_mdelem *gmd) { } void grpc_mdctx_unlock(grpc_mdctx *ctx) { unlock(ctx); } + +int grpc_mdstr_is_legal_header(grpc_mdstr *s) { + /* TODO(ctiller): consider caching this, or computing it on construction */ + const gpr_uint8 *p = GPR_SLICE_START_PTR(s->slice); + const gpr_uint8 *e = GPR_SLICE_END_PTR(s->slice); + for (; p != e; p++) { + if (*p < 32 || *p > 126) return 0; + } + return 1; +} + +int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s) { + /* TODO(ctiller): consider caching this */ + return grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(s->slice), + GPR_SLICE_LENGTH(s->slice)); +} diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h index 21b8ae2b78..e7508718f5 100644 --- a/src/core/transport/metadata.h +++ b/src/core/transport/metadata.h @@ -135,6 +135,9 @@ void grpc_mdelem_unref(grpc_mdelem *md); Does not promise that the returned string has no embedded nulls however. */ const char *grpc_mdstr_as_c_string(grpc_mdstr *s); +int grpc_mdstr_is_legal_header(grpc_mdstr *s); +int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s); + /* Batch mode metadata functions. These API's have equivalents above, but allow taking the mdctx just once, performing a bunch of work, and then leaving the mdctx. */ |