Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / src / core / lib / surface / validate_metadata.cc
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/surface/validate_metadata.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <grpc/grpc.h>
27 #include <grpc/support/alloc.h>
28
29 #include "src/core/lib/gprpp/bitset.h"
30 #include "src/core/lib/gprpp/memory.h"
31 #include "src/core/lib/iomgr/error.h"
32 #include "src/core/lib/slice/slice_internal.h"
33 #include "src/core/lib/slice/slice_string_helpers.h"
34
35 #if __cplusplus > 201103l
36 #define GRPC_VALIDATE_METADATA_CONSTEXPR_FN constexpr
37 #define GRPC_VALIDATE_METADATA_CONSTEXPR_VALUE constexpr
38 #else
39 #define GRPC_VALIDATE_METADATA_CONSTEXPR_FN
40 #define GRPC_VALIDATE_METADATA_CONSTEXPR_VALUE const
41 #endif
42
43 static grpc_error_handle conforms_to(const grpc_slice& slice,
44                                      const grpc_core::BitSet<256>& legal_bits,
45                                      const char* err_desc) {
46   const uint8_t* p = GRPC_SLICE_START_PTR(slice);
47   const uint8_t* e = GRPC_SLICE_END_PTR(slice);
48   for (; p != e; p++) {
49     if (!legal_bits.is_set(*p)) {
50       grpc_error_handle error = grpc_error_set_str(
51           grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc),
52                              GRPC_ERROR_INT_OFFSET,
53                              p - GRPC_SLICE_START_PTR(slice)),
54           GRPC_ERROR_STR_RAW_BYTES,
55           grpc_dump_slice_to_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII));
56       return error;
57     }
58   }
59   return GRPC_ERROR_NONE;
60 }
61
62 static int error2int(grpc_error_handle error) {
63   int r = (error == GRPC_ERROR_NONE);
64   GRPC_ERROR_UNREF(error);
65   return r;
66 }
67
68 namespace {
69 class LegalHeaderKeyBits : public grpc_core::BitSet<256> {
70  public:
71   GRPC_VALIDATE_METADATA_CONSTEXPR_FN LegalHeaderKeyBits() {
72     for (int i = 'a'; i <= 'z'; i++) set(i);
73     for (int i = '0'; i <= '9'; i++) set(i);
74     set('-');
75     set('_');
76     set('.');
77   }
78 };
79 static GRPC_VALIDATE_METADATA_CONSTEXPR_VALUE LegalHeaderKeyBits
80     g_legal_header_key_bits;
81 }  // namespace
82
83 grpc_error_handle grpc_validate_header_key_is_legal(const grpc_slice& slice) {
84   if (GRPC_SLICE_LENGTH(slice) == 0) {
85     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
86         "Metadata keys cannot be zero length");
87   }
88   if (GRPC_SLICE_LENGTH(slice) > UINT32_MAX) {
89     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
90         "Metadata keys cannot be larger than UINT32_MAX");
91   }
92   if (GRPC_SLICE_START_PTR(slice)[0] == ':') {
93     return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
94         "Metadata keys cannot start with :");
95   }
96   return conforms_to(slice, g_legal_header_key_bits, "Illegal header key");
97 }
98
99 int grpc_header_key_is_legal(grpc_slice slice) {
100   return error2int(grpc_validate_header_key_is_legal(slice));
101 }
102
103 namespace {
104 class LegalHeaderNonBinValueBits : public grpc_core::BitSet<256> {
105  public:
106   GRPC_VALIDATE_METADATA_CONSTEXPR_FN LegalHeaderNonBinValueBits() {
107     for (int i = 32; i <= 126; i++) {
108       set(i);
109     }
110   }
111 };
112 static GRPC_VALIDATE_METADATA_CONSTEXPR_VALUE LegalHeaderNonBinValueBits
113     g_legal_header_non_bin_value_bits;
114 }  // namespace
115
116 grpc_error_handle grpc_validate_header_nonbin_value_is_legal(
117     const grpc_slice& slice) {
118   return conforms_to(slice, g_legal_header_non_bin_value_bits,
119                      "Illegal header value");
120 }
121
122 int grpc_header_nonbin_value_is_legal(grpc_slice slice) {
123   return error2int(grpc_validate_header_nonbin_value_is_legal(slice));
124 }
125
126 int grpc_is_binary_header_internal(const grpc_slice& slice) {
127   return grpc_key_is_binary_header(GRPC_SLICE_START_PTR(slice),
128                                    GRPC_SLICE_LENGTH(slice));
129 }
130
131 int grpc_is_binary_header(grpc_slice slice) {
132   return grpc_is_binary_header_internal(slice);
133 }