modernize % encoding routines (#27018)

* modernize % encoding routines

* Automated change: Fix sanity tests

* use bitset

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/26915/head^2
Craig Tiller 3 years ago committed by GitHub
parent 28ccaf4824
commit 5dc93179eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 27
      CMakeLists.txt
  3. 2
      build_autogenerated.yaml
  4. 7
      build_handwritten.yaml
  5. 2
      gRPC-C++.podspec
  6. 2
      gRPC-Core.podspec
  7. 1
      grpc.gemspec
  8. 1
      package.xml
  9. 2
      src/core/ext/filters/http/client/http_client_filter.cc
  10. 4
      src/core/ext/filters/http/server/http_server_filter.cc
  11. 16
      src/core/lib/gprpp/bitset.h
  12. 100
      src/core/lib/slice/percent_encoding.cc
  13. 56
      src/core/lib/slice/percent_encoding.h
  14. 18
      test/core/slice/percent_decode_fuzzer.cc
  15. 20
      test/core/slice/percent_encode_fuzzer.cc
  16. 63
      test/core/slice/percent_encoding_test.cc
  17. 69
      tools/codegen/core/gen_percent_encoding_tables.cc
  18. 1
      tools/doxygen/Doxyfile.c++.internal
  19. 1
      tools/doxygen/Doxyfile.core.internal

@ -1308,6 +1308,7 @@ grpc_cc_library(
public_hdrs = GRPC_PUBLIC_HDRS + GRPC_PUBLIC_EVENT_ENGINE_HDRS,
visibility = ["@grpc:alt_grpc_base_legacy"],
deps = [
"bitset",
"dual_ref_counted",
"gpr_base",
"gpr_codegen",

27
CMakeLists.txt generated

@ -378,7 +378,6 @@ add_custom_target(tools_cxx
DEPENDS
gen_hpack_tables
gen_legal_metadata_characters
gen_percent_encoding_tables
)
add_custom_target(tools
@ -4023,32 +4022,6 @@ target_link_libraries(gen_legal_metadata_characters
)
add_executable(gen_percent_encoding_tables
tools/codegen/core/gen_percent_encoding_tables.cc
)
target_include_directories(gen_percent_encoding_tables
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(gen_percent_encoding_tables
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
)
if(gRPC_BUILD_TESTS)
add_executable(algorithm_test

@ -739,6 +739,7 @@ libs:
- src/core/lib/event_engine/endpoint_config_internal.h
- src/core/lib/event_engine/sockaddr.h
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/bitset.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/match.h
- src/core/lib/gprpp/orphanable.h
@ -1780,6 +1781,7 @@ libs:
- src/core/lib/event_engine/endpoint_config_internal.h
- src/core/lib/event_engine/sockaddr.h
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/bitset.h
- src/core/lib/gprpp/dual_ref_counted.h
- src/core/lib/gprpp/match.h
- src/core/lib/gprpp/orphanable.h

@ -41,13 +41,6 @@ targets:
src:
- tools/codegen/core/gen_legal_metadata_characters.cc
deps: []
- name: gen_percent_encoding_tables
build: tool
language: c++
src:
- tools/codegen/core/gen_percent_encoding_tables.cc
deps: []
uses_polling: false
configs:
asan:
CC: clang

2
gRPC-C++.podspec generated

@ -544,6 +544,7 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/useful.h',
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/bitset.h',
'src/core/lib/gprpp/construct_destruct.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
@ -1207,6 +1208,7 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/useful.h',
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/bitset.h',
'src/core/lib/gprpp/construct_destruct.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',

2
gRPC-Core.podspec generated

@ -915,6 +915,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/arena.cc',
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/bitset.h',
'src/core/lib/gprpp/construct_destruct.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
@ -1794,6 +1795,7 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/useful.h',
'src/core/lib/gprpp/arena.h',
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/bitset.h',
'src/core/lib/gprpp/construct_destruct.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',

1
grpc.gemspec generated

@ -828,6 +828,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/arena.cc )
s.files += %w( src/core/lib/gprpp/arena.h )
s.files += %w( src/core/lib/gprpp/atomic.h )
s.files += %w( src/core/lib/gprpp/bitset.h )
s.files += %w( src/core/lib/gprpp/construct_destruct.h )
s.files += %w( src/core/lib/gprpp/debug_location.h )
s.files += %w( src/core/lib/gprpp/dual_ref_counted.h )

1
package.xml generated

@ -808,6 +808,7 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/arena.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/arena.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/atomic.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/bitset.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/construct_destruct.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/debug_location.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/dual_ref_counted.h" role="src" />

@ -142,7 +142,7 @@ static grpc_error_handle client_filter_incoming_metadata(
}
if (b->idx.named.grpc_message != nullptr) {
grpc_slice pct_decoded_msg = grpc_permissive_percent_decode_slice(
grpc_slice pct_decoded_msg = grpc_core::PermissivePercentDecodeSlice(
GRPC_MDVALUE(b->idx.named.grpc_message->md));
if (grpc_slice_is_equivalent(pct_decoded_msg,
GRPC_MDVALUE(b->idx.named.grpc_message->md))) {

@ -103,9 +103,9 @@ struct channel_data {
static grpc_error_handle hs_filter_outgoing_metadata(grpc_metadata_batch* b) {
if (b->idx.named.grpc_message != nullptr) {
grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
grpc_slice pct_encoded_msg = grpc_core::PercentEncodeSlice(
GRPC_MDVALUE(b->idx.named.grpc_message->md),
grpc_compatible_percent_encoding_unreserved_bytes);
grpc_core::PercentEncodingType::Compatible);
if (grpc_slice_is_equivalent(pct_encoded_msg,
GRPC_MDVALUE(b->idx.named.grpc_message->md))) {
grpc_slice_unref_internal(pct_encoded_msg);

@ -19,6 +19,12 @@
#include <utility>
#if __cplusplus > 201103l
#define GRPC_BITSET_CONSTEXPR_MUTATOR constexpr
#else
#define GRPC_BITSET_CONSTEXPR_MUTATOR
#endif
namespace grpc_core {
// Given a bit count as an integer, vend as member type `Type` a type with
@ -79,10 +85,12 @@ class BitSet {
constexpr BitSet() : units_{} {}
// Set bit i to true
void set(int i) { units_[unit_for(i)] |= mask_for(i); }
GRPC_BITSET_CONSTEXPR_MUTATOR void set(int i) {
units_[unit_for(i)] |= mask_for(i);
}
// Set bit i to is_set
void set(int i, bool is_set) {
GRPC_BITSET_CONSTEXPR_MUTATOR void set(int i, bool is_set) {
if (is_set) {
set(i);
} else {
@ -91,7 +99,9 @@ class BitSet {
}
// Set bit i to false
void clear(int i) { units_[unit_for(i)] &= ~mask_for(i); }
GRPC_BITSET_CONSTEXPR_MUTATOR void clear(int i) {
units_[unit_for(i)] &= ~mask_for(i);
}
// Return true if bit i is set
constexpr bool is_set(int i) const {

@ -22,26 +22,65 @@
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/bitset.h"
#include "src/core/lib/slice/slice_internal.h"
const uint8_t grpc_url_percent_encoding_unreserved_bytes[256 / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0xfe, 0xff, 0xff,
0x87, 0xfe, 0xff, 0xff, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t grpc_compatible_percent_encoding_unreserved_bytes[256 / 8] = {
0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static bool is_unreserved_character(uint8_t c,
const uint8_t* unreserved_bytes) {
return ((unreserved_bytes[c / 8] >> (c % 8)) & 1) != 0;
#include <cstdint>
#if __cplusplus > 201103l
#define GRPC_PCTENCODE_CONSTEXPR_FN constexpr
#define GRPC_PCTENCODE_CONSTEXPR_VALUE constexpr
#else
#define GRPC_PCTENCODE_CONSTEXPR_FN
#define GRPC_PCTENCODE_CONSTEXPR_VALUE const
#endif
namespace grpc_core {
namespace {
class UrlTable : public BitSet<256> {
public:
GRPC_PCTENCODE_CONSTEXPR_FN UrlTable() {
for (int i = 'a'; i <= 'z'; i++) set(i);
for (int i = 'A'; i <= 'Z'; i++) set(i);
for (int i = '0'; i <= '9'; i++) set(i);
set('-');
set('_');
set('.');
set('~');
}
};
static GRPC_PCTENCODE_CONSTEXPR_VALUE UrlTable g_url_table;
class CompatibleTable : public BitSet<256> {
public:
GRPC_PCTENCODE_CONSTEXPR_FN CompatibleTable() {
for (int i = 32; i <= 126; i++) {
if (i == '%') continue;
set(i);
}
}
};
static GRPC_PCTENCODE_CONSTEXPR_VALUE CompatibleTable g_compatible_table;
const BitSet<256>& LookupTableForPercentEncodingType(PercentEncodingType type) {
switch (type) {
case PercentEncodingType::URL:
return g_url_table;
case PercentEncodingType::Compatible:
return g_compatible_table;
}
}
} // namespace
grpc_slice grpc_percent_encode_slice(const grpc_slice& slice,
const uint8_t* unreserved_bytes) {
grpc_slice PercentEncodeSlice(const grpc_slice& slice,
PercentEncodingType type) {
static const uint8_t hex[] = "0123456789ABCDEF";
const BitSet<256>& lut = LookupTableForPercentEncodingType(type);
// first pass: count the number of bytes needed to output this string
size_t output_length = 0;
const uint8_t* slice_start = GRPC_SLICE_START_PTR(slice);
@ -49,7 +88,7 @@ grpc_slice grpc_percent_encode_slice(const grpc_slice& slice,
const uint8_t* p;
bool any_reserved_bytes = false;
for (p = slice_start; p < slice_end; p++) {
bool unres = is_unreserved_character(*p, unreserved_bytes);
bool unres = lut.is_set(*p);
output_length += unres ? 1 : 3;
any_reserved_bytes |= !unres;
}
@ -61,7 +100,7 @@ grpc_slice grpc_percent_encode_slice(const grpc_slice& slice,
grpc_slice out = GRPC_SLICE_MALLOC(output_length);
uint8_t* q = GRPC_SLICE_START_PTR(out);
for (p = slice_start; p < slice_end; p++) {
if (is_unreserved_character(*p, unreserved_bytes)) {
if (lut.is_set(*p)) {
*q++ = *p;
} else {
*q++ = '%';
@ -86,34 +125,33 @@ static uint8_t dehex(uint8_t c) {
GPR_UNREACHABLE_CODE(return 255);
}
bool grpc_strict_percent_decode_slice(const grpc_slice& slice_in,
const uint8_t* unreserved_bytes,
grpc_slice* slice_out) {
absl::optional<grpc_slice> PercentDecodeSlice(const grpc_slice& slice_in,
PercentEncodingType type) {
const uint8_t* p = GRPC_SLICE_START_PTR(slice_in);
const uint8_t* in_end = GRPC_SLICE_END_PTR(slice_in);
size_t out_length = 0;
bool any_percent_encoded_stuff = false;
const BitSet<256>& lut = LookupTableForPercentEncodingType(type);
while (p != in_end) {
if (*p == '%') {
if (!valid_hex(++p, in_end)) return false;
if (!valid_hex(++p, in_end)) return false;
if (!valid_hex(++p, in_end)) return {};
if (!valid_hex(++p, in_end)) return {};
p++;
out_length++;
any_percent_encoded_stuff = true;
} else if (is_unreserved_character(*p, unreserved_bytes)) {
} else if (lut.is_set(*p)) {
p++;
out_length++;
} else {
return false;
return {};
}
}
if (!any_percent_encoded_stuff) {
*slice_out = grpc_slice_ref_internal(slice_in);
return true;
return grpc_slice_ref_internal(slice_in);
}
p = GRPC_SLICE_START_PTR(slice_in);
*slice_out = GRPC_SLICE_MALLOC(out_length);
uint8_t* q = GRPC_SLICE_START_PTR(*slice_out);
grpc_slice slice_out = GRPC_SLICE_MALLOC(out_length);
uint8_t* q = GRPC_SLICE_START_PTR(slice_out);
while (p != in_end) {
if (*p == '%') {
*q++ = static_cast<uint8_t>(dehex(p[1]) << 4) | (dehex(p[2]));
@ -122,11 +160,11 @@ bool grpc_strict_percent_decode_slice(const grpc_slice& slice_in,
*q++ = *p++;
}
}
GPR_ASSERT(q == GRPC_SLICE_END_PTR(*slice_out));
return true;
GPR_ASSERT(q == GRPC_SLICE_END_PTR(slice_out));
return slice_out;
}
grpc_slice grpc_permissive_percent_decode_slice(const grpc_slice& slice_in) {
grpc_slice PermissivePercentDecodeSlice(const grpc_slice& slice_in) {
const uint8_t* p = GRPC_SLICE_START_PTR(slice_in);
const uint8_t* in_end = GRPC_SLICE_END_PTR(slice_in);
size_t out_length = 0;
@ -167,3 +205,5 @@ grpc_slice grpc_permissive_percent_decode_slice(const grpc_slice& slice_in) {
GPR_ASSERT(q == GRPC_SLICE_END_PTR(out));
return out;
}
} // namespace grpc_core

@ -31,35 +31,35 @@
#include <stdbool.h>
#include <grpc/slice.h>
#include "absl/types/optional.h"
/* URL percent encoding spec bitfield (usabel as 'unreserved_bytes' in
grpc_percent_encode_slice, grpc_strict_percent_decode_slice).
Flags [A-Za-z0-9-_.~] as unreserved bytes for the percent encoding routines
*/
extern const uint8_t grpc_url_percent_encoding_unreserved_bytes[256 / 8];
/* URL percent encoding spec bitfield (usabel as 'unreserved_bytes' in
grpc_percent_encode_slice, grpc_strict_percent_decode_slice).
Flags ascii7 non-control characters excluding '%' as unreserved bytes for the
percent encoding routines */
extern const uint8_t grpc_compatible_percent_encoding_unreserved_bytes[256 / 8];
namespace grpc_core {
/* Percent-encode a slice, returning the new slice (this cannot fail):
unreserved_bytes is a bitfield indicating which bytes are considered
unreserved and thus do not need percent encoding */
grpc_slice grpc_percent_encode_slice(const grpc_slice& slice,
const uint8_t* unreserved_bytes);
/* Percent-decode a slice, strictly.
If the input is legal (contains no unreserved bytes, and legal % encodings),
returns true and sets *slice_out to the decoded slice.
If the input is not legal, returns false and leaves *slice_out untouched.
unreserved_bytes is a bitfield indicating which bytes are considered
unreserved and thus do not need percent encoding */
bool grpc_strict_percent_decode_slice(const grpc_slice& slice_in,
const uint8_t* unreserved_bytes,
grpc_slice* slice_out);
/* Percent-decode a slice, permissively.
If a % triplet can not be decoded, pass it through verbatim.
This cannot fail. */
grpc_slice grpc_permissive_percent_decode_slice(const grpc_slice& slice_in);
enum class PercentEncodingType {
// Flags [A-Za-z0-9-_.~] as unreserved bytes for the percent encoding routines
URL,
// Flags ascii7 non-control characters excluding '%' as unreserved bytes for
// the
// percent encoding routines
Compatible
};
// Percent-encode a slice, returning the new slice (this cannot fail):
// unreserved_bytes is a bitfield indicating which bytes are considered
// unreserved and thus do not need percent encoding
grpc_slice PercentEncodeSlice(const grpc_slice& slice,
PercentEncodingType type);
// Percent-decode a slice, strictly.
// If the input is legal (contains no unreserved bytes, and legal % encodings),
// returns the decoded slice.
// If the input is not legal, returns {}.
absl::optional<grpc_slice> PercentDecodeSlice(const grpc_slice& slice_in,
PercentEncodingType type);
// Percent-decode a slice, permissively.
// If a % triplet can not be decoded, pass it through verbatim.
// This cannot fail.
grpc_slice PermissivePercentDecodeSlice(const grpc_slice& slice_in);
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_SLICE_PERCENT_ENCODING_H */

@ -32,16 +32,18 @@ bool leak_check = true;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
grpc_init();
grpc_slice input = grpc_slice_from_copied_buffer((const char*)data, size);
grpc_slice output;
if (grpc_strict_percent_decode_slice(
input, grpc_url_percent_encoding_unreserved_bytes, &output)) {
grpc_slice_unref(output);
absl::optional<grpc_slice> output;
output =
grpc_core::PercentDecodeSlice(input, grpc_core::PercentEncodingType::URL);
if (output.has_value()) {
grpc_slice_unref(*output);
}
if (grpc_strict_percent_decode_slice(
input, grpc_compatible_percent_encoding_unreserved_bytes, &output)) {
grpc_slice_unref(output);
output = grpc_core::PercentDecodeSlice(
input, grpc_core::PercentEncodingType::Compatible);
if (output.has_value()) {
grpc_slice_unref(*output);
}
grpc_slice_unref(grpc_permissive_percent_decode_slice(input));
grpc_slice_unref(grpc_core::PermissivePercentDecodeSlice(input));
grpc_slice_unref(input);
grpc_shutdown();
return 0;

@ -29,28 +29,30 @@
bool squelch = true;
bool leak_check = true;
static void test(const uint8_t* data, size_t size, const uint8_t* dict) {
static void test(const uint8_t* data, size_t size,
grpc_core::PercentEncodingType type) {
grpc_init();
grpc_slice input =
grpc_slice_from_copied_buffer(reinterpret_cast<const char*>(data), size);
grpc_slice output = grpc_percent_encode_slice(input, dict);
grpc_slice decoded_output;
grpc_slice output = grpc_core::PercentEncodeSlice(input, type);
absl::optional<grpc_slice> decoded_output =
grpc_core::PercentDecodeSlice(output, type);
// encoder must always produce decodable output
GPR_ASSERT(grpc_strict_percent_decode_slice(output, dict, &decoded_output));
GPR_ASSERT(decoded_output.has_value());
grpc_slice permissive_decoded_output =
grpc_permissive_percent_decode_slice(output);
grpc_core::PermissivePercentDecodeSlice(output);
// and decoded output must always match the input
GPR_ASSERT(grpc_slice_eq(input, decoded_output));
GPR_ASSERT(grpc_slice_eq(input, *decoded_output));
GPR_ASSERT(grpc_slice_eq(input, permissive_decoded_output));
grpc_slice_unref(input);
grpc_slice_unref(output);
grpc_slice_unref(decoded_output);
grpc_slice_unref(*decoded_output);
grpc_slice_unref(permissive_decoded_output);
grpc_shutdown();
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
test(data, size, grpc_url_percent_encoding_unreserved_bytes);
test(data, size, grpc_compatible_percent_encoding_unreserved_bytes);
test(data, size, grpc_core::PercentEncodingType::URL);
test(data, size, grpc_core::PercentEncodingType::Compatible);
return 0;
}

@ -35,7 +35,8 @@
sizeof(permissive_unencoded) - 1, dict)
static void test_vector(const char* raw, size_t raw_length, const char* encoded,
size_t encoded_length, const uint8_t* dict) {
size_t encoded_length,
grpc_core::PercentEncodingType type) {
char* raw_msg = gpr_dump(raw, raw_length, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char* encoded_msg =
gpr_dump(encoded, encoded_length, GPR_DUMP_HEX | GPR_DUMP_ASCII);
@ -46,17 +47,17 @@ static void test_vector(const char* raw, size_t raw_length, const char* encoded,
grpc_slice raw_slice = grpc_slice_from_copied_buffer(raw, raw_length);
grpc_slice encoded_slice =
grpc_slice_from_copied_buffer(encoded, encoded_length);
grpc_slice raw2encoded_slice = grpc_percent_encode_slice(raw_slice, dict);
grpc_slice encoded2raw_slice;
GPR_ASSERT(grpc_strict_percent_decode_slice(encoded_slice, dict,
&encoded2raw_slice));
grpc_slice raw2encoded_slice = grpc_core::PercentEncodeSlice(raw_slice, type);
absl::optional<grpc_slice> encoded2raw_slice =
grpc_core::PercentDecodeSlice(encoded_slice, type);
GPR_ASSERT(encoded2raw_slice.has_value());
grpc_slice encoded2raw_permissive_slice =
grpc_permissive_percent_decode_slice(encoded_slice);
grpc_core::PermissivePercentDecodeSlice(encoded_slice);
char* raw2encoded_msg =
grpc_dump_slice(raw2encoded_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char* encoded2raw_msg =
grpc_dump_slice(encoded2raw_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
grpc_dump_slice(*encoded2raw_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
char* encoded2raw_permissive_msg = grpc_dump_slice(
encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_DEBUG,
@ -67,11 +68,11 @@ static void test_vector(const char* raw, size_t raw_length, const char* encoded,
gpr_free(encoded2raw_msg);
gpr_free(encoded2raw_permissive_msg);
GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_slice));
GPR_ASSERT(grpc_slice_eq(raw_slice, *encoded2raw_slice));
GPR_ASSERT(grpc_slice_eq(raw_slice, encoded2raw_permissive_slice));
GPR_ASSERT(grpc_slice_eq(encoded_slice, raw2encoded_slice));
grpc_slice_unref(encoded2raw_slice);
grpc_slice_unref(*encoded2raw_slice);
grpc_slice_unref(encoded2raw_permissive_slice);
grpc_slice_unref(raw2encoded_slice);
grpc_slice_unref(raw_slice);
@ -82,7 +83,7 @@ static void test_nonconformant_vector(const char* encoded,
size_t encoded_length,
const char* permissive_unencoded,
size_t permissive_unencoded_length,
const uint8_t* dict) {
grpc_core::PercentEncodingType type) {
char* permissive_unencoded_msg =
gpr_dump(permissive_unencoded, permissive_unencoded_length,
GPR_DUMP_HEX | GPR_DUMP_ASCII);
@ -97,11 +98,11 @@ static void test_nonconformant_vector(const char* encoded,
permissive_unencoded, permissive_unencoded_length);
grpc_slice encoded_slice =
grpc_slice_from_copied_buffer(encoded, encoded_length);
grpc_slice encoded2raw_slice;
GPR_ASSERT(!grpc_strict_percent_decode_slice(encoded_slice, dict,
&encoded2raw_slice));
absl::optional<grpc_slice> encoded2raw_slice =
grpc_core::PercentDecodeSlice(encoded_slice, type);
GPR_ASSERT(!encoded2raw_slice.has_value());
grpc_slice encoded2raw_permissive_slice =
grpc_permissive_percent_decode_slice(encoded_slice);
grpc_core::PermissivePercentDecodeSlice(encoded_slice);
char* encoded2raw_permissive_msg = grpc_dump_slice(
encoded2raw_permissive_slice, GPR_DUMP_HEX | GPR_DUMP_ASCII);
@ -123,25 +124,21 @@ int main(int argc, char** argv) {
TEST_VECTOR(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~",
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~",
grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\x00", "%00", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\x01", "%01", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("a b", "a%20b", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR(" b", "%20b", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("a b", "a b", grpc_compatible_percent_encoding_unreserved_bytes);
TEST_VECTOR(" b", " b", grpc_compatible_percent_encoding_unreserved_bytes);
TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%", "%",
grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%A", "%A",
grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%AG", "%AG",
grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("\0", "\0",
grpc_url_percent_encoding_unreserved_bytes);
grpc_core::PercentEncodingType::URL);
TEST_VECTOR("\x00", "%00", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("\x01", "%01", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("a b", "a%20b", grpc_core::PercentEncodingType::URL);
TEST_VECTOR(" b", "%20b", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("a b", "a b", grpc_core::PercentEncodingType::Compatible);
TEST_VECTOR(" b", " b", grpc_core::PercentEncodingType::Compatible);
TEST_VECTOR("\x0f", "%0F", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("\xff", "%FF", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("\xee", "%EE", grpc_core::PercentEncodingType::URL);
TEST_VECTOR("%2", "%252", grpc_core::PercentEncodingType::URL);
TEST_NONCONFORMANT_VECTOR("%", "%", grpc_core::PercentEncodingType::URL);
TEST_NONCONFORMANT_VECTOR("%A", "%A", grpc_core::PercentEncodingType::URL);
TEST_NONCONFORMANT_VECTOR("%AG", "%AG", grpc_core::PercentEncodingType::URL);
TEST_NONCONFORMANT_VECTOR("\0", "\0", grpc_core::PercentEncodingType::URL);
grpc_shutdown();
return 0;
}

@ -1,69 +0,0 @@
/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/* generates constant table for metadata.cc */
#include <stdio.h>
#include <string.h>
static unsigned char legal_bits[256 / 8];
static void legal(int x) {
int byte = x / 8;
int bit = x % 8;
/* NB: the following integer arithmetic operation needs to be in its
* expanded form due to the "integral promotion" performed (see section
* 3.2.1.1 of the C89 draft standard). A cast to the smaller container type
* is then required to avoid the compiler warning */
legal_bits[byte] =
(unsigned char)((legal_bits[byte] | (unsigned char)(1 << bit)));
}
static void dump(const char *name) {
int i;
printf("const uint8_t %s[256/8] = ", name);
for (i = 0; i < 256 / 8; i++)
printf("%c 0x%02x", i ? ',' : '{', legal_bits[i]);
printf(" };\n");
}
static void clear(void) { memset(legal_bits, 0, sizeof(legal_bits)); }
int main(void) {
int i;
clear();
for (i = 'a'; i <= 'z'; i++) legal(i);
for (i = 'A'; i <= 'Z'; i++) legal(i);
for (i = '0'; i <= '9'; i++) legal(i);
legal('-');
legal('_');
legal('.');
legal('~');
dump("grpc_url_percent_encoding_unreserved_bytes");
clear();
for (i = 32; i <= 126; i++) {
if (i == '%') continue;
legal(i);
}
dump("grpc_compatible_percent_encoding_unreserved_bytes");
return 0;
}

@ -1761,6 +1761,7 @@ src/core/lib/gpr/wrap_memcpy.cc \
src/core/lib/gprpp/arena.cc \
src/core/lib/gprpp/arena.h \
src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/bitset.h \
src/core/lib/gprpp/construct_destruct.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/dual_ref_counted.h \

@ -1600,6 +1600,7 @@ src/core/lib/gprpp/README.md \
src/core/lib/gprpp/arena.cc \
src/core/lib/gprpp/arena.h \
src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/bitset.h \
src/core/lib/gprpp/construct_destruct.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/dual_ref_counted.h \

Loading…
Cancel
Save