Merge pull request #4640 from murgatroid99/node_use_core_metadata_check

Use core metadata validation functions in Node library
pull/4625/head^2
Craig Tiller 9 years ago
commit ad8bc063dd
  1. 8
      src/node/ext/call.cc
  2. 50
      src/node/ext/node_grpc.cc
  3. 20
      src/node/src/metadata.js

@ -95,10 +95,6 @@ Local<Value> nanErrorWithCode(const char *msg, grpc_call_error code) {
return scope.Escape(err); return scope.Escape(err);
} }
bool EndsWith(const char *str, const char *substr) {
return strcmp(str+strlen(str)-strlen(substr), substr) == 0;
}
bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array, bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array,
shared_ptr<Resources> resources) { shared_ptr<Resources> resources) {
HandleScope scope; HandleScope scope;
@ -126,7 +122,7 @@ bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array,
grpc_metadata *current = &array->metadata[array->count]; grpc_metadata *current = &array->metadata[array->count];
current->key = **utf8_key; current->key = **utf8_key;
// Only allow binary headers for "-bin" keys // Only allow binary headers for "-bin" keys
if (EndsWith(current->key, "-bin")) { if (grpc_is_binary_header(current->key, strlen(current->key))) {
if (::node::Buffer::HasInstance(value)) { if (::node::Buffer::HasInstance(value)) {
current->value = ::node::Buffer::Data(value); current->value = ::node::Buffer::Data(value);
current->value_length = ::node::Buffer::Length(value); current->value_length = ::node::Buffer::Length(value);
@ -180,7 +176,7 @@ Local<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
} else { } else {
array = Local<Array>::Cast(maybe_array.ToLocalChecked()); array = Local<Array>::Cast(maybe_array.ToLocalChecked());
} }
if (EndsWith(elem->key, "-bin")) { if (grpc_is_binary_header(elem->key, strlen(elem->key))) {
Nan::Set(array, index_map[elem->key], Nan::Set(array, index_map[elem->key],
MakeFastBuffer( MakeFastBuffer(
Nan::CopyBuffer(elem->value, Nan::CopyBuffer(elem->value,

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -44,6 +44,7 @@
#include "completion_queue_async_worker.h" #include "completion_queue_async_worker.h"
#include "server_credentials.h" #include "server_credentials.h"
using v8::FunctionTemplate;
using v8::Local; using v8::Local;
using v8::Value; using v8::Value;
using v8::Object; using v8::Object;
@ -230,6 +231,40 @@ void InitWriteFlags(Local<Object> exports) {
Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS); Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS);
} }
NAN_METHOD(MetadataKeyIsLegal) {
if (!info[0]->IsString()) {
return Nan::ThrowTypeError(
"headerKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
char *key_str = *Nan::Utf8String(key);
info.GetReturnValue().Set(static_cast<bool>(
grpc_header_key_is_legal(key_str, static_cast<size_t>(key->Length()))));
}
NAN_METHOD(MetadataNonbinValueIsLegal) {
if (!info[0]->IsString()) {
return Nan::ThrowTypeError(
"metadataNonbinValueIsLegal's argument must be a string");
}
Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
char *value_str = *Nan::Utf8String(value);
info.GetReturnValue().Set(static_cast<bool>(
grpc_header_nonbin_value_is_legal(
value_str, static_cast<size_t>(value->Length()))));
}
NAN_METHOD(MetadataKeyIsBinary) {
if (!info[0]->IsString()) {
return Nan::ThrowTypeError(
"metadataKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
char *key_str = *Nan::Utf8String(key);
info.GetReturnValue().Set(static_cast<bool>(
grpc_is_binary_header(key_str, static_cast<size_t>(key->Length()))));
}
void init(Local<Object> exports) { void init(Local<Object> exports) {
Nan::HandleScope scope; Nan::HandleScope scope;
grpc_init(); grpc_init();
@ -247,6 +282,19 @@ void init(Local<Object> exports) {
grpc::node::Server::Init(exports); grpc::node::Server::Init(exports);
grpc::node::CompletionQueueAsyncWorker::Init(exports); grpc::node::CompletionQueueAsyncWorker::Init(exports);
grpc::node::ServerCredentials::Init(exports); grpc::node::ServerCredentials::Init(exports);
// Attach a few utility functions directly to the module
Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(),
Nan::GetFunction(
Nan::New<FunctionTemplate>(MetadataKeyIsLegal)).ToLocalChecked());
Nan::Set(exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(),
Nan::GetFunction(
Nan::New<FunctionTemplate>(MetadataNonbinValueIsLegal)
).ToLocalChecked());
Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(),
Nan::GetFunction(
Nan::New<FunctionTemplate>(MetadataKeyIsBinary)
).ToLocalChecked());
} }
NODE_MODULE(grpc_node, init) NODE_MODULE(grpc_node, init)

@ -1,6 +1,6 @@
/* /*
* *
* Copyright 2015, Google Inc. * Copyright 2015-2016, Google Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -49,6 +49,8 @@
var _ = require('lodash'); var _ = require('lodash');
var grpc = require('bindings')('grpc_node');
/** /**
* Class for storing metadata. Keys are normalized to lowercase ASCII. * Class for storing metadata. Keys are normalized to lowercase ASCII.
* @constructor * @constructor
@ -58,15 +60,16 @@ function Metadata() {
} }
function normalizeKey(key) { function normalizeKey(key) {
if (!(/^[A-Za-z\d_-]+$/.test(key))) { key = key.toLowerCase();
throw new Error('Metadata keys must be nonempty strings containing only ' + if (grpc.metadataKeyIsLegal(key)) {
'alphanumeric characters and hyphens'); return key;
} else {
throw new Error('Metadata key contains illegal characters');
} }
return key.toLowerCase();
} }
function validate(key, value) { function validate(key, value) {
if (_.endsWith(key, '-bin')) { if (grpc.metadataKeyIsBinary(key)) {
if (!(value instanceof Buffer)) { if (!(value instanceof Buffer)) {
throw new Error('keys that end with \'-bin\' must have Buffer values'); throw new Error('keys that end with \'-bin\' must have Buffer values');
} }
@ -75,9 +78,8 @@ function validate(key, value) {
throw new Error( throw new Error(
'keys that don\'t end with \'-bin\' must have String values'); 'keys that don\'t end with \'-bin\' must have String values');
} }
if (!(/^[\x20-\x7E]*$/.test(value))) { if (!grpc.metadataNonbinValueIsLegal(value)) {
throw new Error('Metadata string values can only contain printable ' + throw new Error('Metadata string value contains illegal characters');
'ASCII characters and space');
} }
} }
} }

Loading…
Cancel
Save