decode_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Google LLC nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Internal implementation details of the decoder that are shared between
30  * decode.c and decode_fast.c.
31  */
32 
33 #ifndef UPB_DECODE_INT_H_
34 #define UPB_DECODE_INT_H_
35 
36 #include <setjmp.h>
37 
39 #include "upb/decode.h"
40 #include "upb/msg_internal.h"
41 #include "upb/upb_internal.h"
42 
43 /* Must be last. */
44 #include "upb/port_def.inc"
45 
46 #define DECODE_NOGROUP (uint32_t) - 1
47 
48 typedef struct upb_Decoder {
49  const char* end; /* Can read up to 16 bytes slop beyond this. */
50  const char* limit_ptr; /* = end + UPB_MIN(limit, 0) */
51  upb_Message* unknown_msg; /* If non-NULL, add unknown data at buffer flip. */
52  const char* unknown; /* Start of unknown data. */
54  extreg; /* For looking up extensions during the parse. */
55  int limit; /* Submessage limit relative to end. */
56  int depth; /* Tracks recursion depth to bound stack usage. */
57  uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
60  char patch[32];
62  jmp_buf err;
63 
64 #ifndef NDEBUG
65  const char* debug_tagstart;
66  const char* debug_valstart;
67 #endif
68 } upb_Decoder;
69 
70 /* Error function that will abort decoding with longjmp(). We can't declare this
71  * UPB_NORETURN, even though it is appropriate, because if we do then compilers
72  * will "helpfully" refuse to tailcall to it
73  * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal
74  * of our optimizations. That is also why we must declare it in a separate file,
75  * otherwise the compiler will see that it calls longjmp() and deduce that it is
76  * noreturn. */
77 const char* fastdecode_err(upb_Decoder* d, int status);
78 
79 extern const uint8_t upb_utf8_offsets[];
80 
82 bool decode_verifyutf8_inl(const char* ptr, int len) {
83  const char* end = ptr + len;
84 
85  // Check 8 bytes at a time for any non-ASCII char.
86  while (end - ptr >= 8) {
87  uint64_t data;
88  memcpy(&data, ptr, 8);
89  if (data & 0x8080808080808080) goto non_ascii;
90  ptr += 8;
91  }
92 
93  // Check one byte at a time for non-ASCII.
94  while (ptr < end) {
95  if (*ptr & 0x80) goto non_ascii;
96  ptr++;
97  }
98 
99  return true;
100 
101 non_ascii:
102  return utf8_range2((const unsigned char*)ptr, end - ptr) == 0;
103 }
104 
105 const char* decode_checkrequired(upb_Decoder* d, const char* ptr,
106  const upb_Message* msg,
107  const upb_MiniTable* l);
108 
109 /* x86-64 pointers always have the high 16 bits matching. So we can shift
110  * left 8 and right 8 without loss of information. */
112  return ((intptr_t)tablep << 8) | tablep->table_mask;
113 }
114 
116  return (const upb_MiniTable*)(table >> 8);
117 }
118 
120 const char* decode_isdonefallback_inl(upb_Decoder* d, const char* ptr,
121  int overrun, int* status) {
122  if (overrun < d->limit) {
123  /* Need to copy remaining data into patch buffer. */
124  UPB_ASSERT(overrun < 16);
125  if (d->unknown_msg) {
126  if (!_upb_Message_AddUnknown(d->unknown_msg, d->unknown, ptr - d->unknown,
127  &d->arena)) {
129  return NULL;
130  }
131  d->unknown = &d->patch[0] + overrun;
132  }
133  memset(d->patch + 16, 0, 16);
134  memcpy(d->patch, d->end, 16);
135  ptr = &d->patch[0] + overrun;
136  d->end = &d->patch[16];
137  d->limit -= 16;
138  d->limit_ptr = d->end + d->limit;
139  d->options &= ~kUpb_DecodeOption_AliasString;
140  UPB_ASSERT(ptr < d->limit_ptr);
141  return ptr;
142  } else {
144  return NULL;
145  }
146 }
147 
148 const char* decode_isdonefallback(upb_Decoder* d, const char* ptr, int overrun);
149 
151 bool decode_isdone(upb_Decoder* d, const char** ptr) {
152  int overrun = *ptr - d->end;
153  if (UPB_LIKELY(*ptr < d->limit_ptr)) {
154  return false;
155  } else if (UPB_LIKELY(overrun == d->limit)) {
156  return true;
157  } else {
158  *ptr = decode_isdonefallback(d, *ptr, overrun);
159  return false;
160  }
161 }
162 
163 #if UPB_FASTTABLE
165 const char* fastdecode_tagdispatch(upb_Decoder* d, const char* ptr,
167  uint64_t hasbits, uint64_t tag) {
168  const upb_MiniTable* table_p = decode_totablep(table);
169  uint8_t mask = table;
170  uint64_t data;
171  size_t idx = tag & mask;
172  UPB_ASSUME((idx & 7) == 0);
173  idx >>= 3;
174  data = table_p->fasttable[idx].field_data ^ tag;
175  UPB_MUSTTAIL return table_p->fasttable[idx].field_parser(d, ptr, msg, table,
176  hasbits, data);
177 }
178 #endif
179 
181  uint16_t tag;
182  memcpy(&tag, ptr, 2);
183  return tag;
184 }
185 
187  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
188 }
189 
190 UPB_INLINE int decode_pushlimit(upb_Decoder* d, const char* ptr, int size) {
191  int limit = size + (int)(ptr - d->end);
192  int delta = d->limit - limit;
194  d->limit = limit;
195  d->limit_ptr = d->end + UPB_MIN(0, limit);
197  return delta;
198 }
199 
201  int saved_delta) {
202  UPB_ASSERT(ptr - d->end == d->limit);
204  d->limit += saved_delta;
205  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
207 }
208 
209 #include "upb/port_undef.inc"
210 
211 #endif /* UPB_DECODE_INT_H_ */
_upb_FastTable_Entry::field_data
uint64_t field_data
Definition: msg_internal.h:132
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
upb_internal.h
memset
return memset(p, 0, total)
upb_Decoder
Definition: decode_internal.h:48
decode_isdonefallback
const char * decode_isdonefallback(upb_Decoder *d, const char *ptr, int overrun)
Definition: decode.c:307
uint16_t
unsigned short uint16_t
Definition: stdint-msvc2008.h:79
decode_poplimit
UPB_INLINE void decode_poplimit(upb_Decoder *d, const char *ptr, int saved_delta)
Definition: decode_internal.h:200
upb_Decoder::missing_required
bool missing_required
Definition: decode_internal.h:59
status
absl::Status status
Definition: rls.cc:251
upb_MiniTable
Definition: msg_internal.h:185
kUpb_DecodeStatus_Malformed
@ kUpb_DecodeStatus_Malformed
Definition: decode.h:73
upb_Decoder::depth
int depth
Definition: decode_internal.h:56
upb_Decoder::patch
char patch[32]
Definition: decode_internal.h:60
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
upb_MiniTable::fasttable
_upb_FastTable_Entry fasttable[]
Definition: msg_internal.h:199
UPB_MIN
#define UPB_MIN(x, y)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:126
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
decode_checkrequired
const char * decode_checkrequired(upb_Decoder *d, const char *ptr, const upb_Message *msg, const upb_MiniTable *l)
Definition: decode.c:715
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
decode_pushlimit
UPB_INLINE int decode_pushlimit(upb_Decoder *d, const char *ptr, int size)
Definition: decode_internal.h:190
xds_interop_client.int
int
Definition: xds_interop_client.py:113
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
decode.h
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
upb_Decoder::unknown_msg
upb_Message * unknown_msg
Definition: decode_internal.h:51
UPB_ASSUME
#define UPB_ASSUME(expr)
Definition: php-upb.c:141
upb_MiniTable::table_mask
uint8_t table_mask
Definition: msg_internal.h:194
upb_Decoder::unknown
const char * unknown
Definition: decode_internal.h:52
utf8_range2
static int utf8_range2(const unsigned char *data, int len)
Definition: utf8_range.h:6
fastdecode_loadtag
UPB_INLINE uint32_t fastdecode_loadtag(const char *ptr)
Definition: decode_internal.h:180
UPB_INLINE
#define UPB_INLINE
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:53
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
upb_Decoder::extreg
const upb_ExtensionRegistry * extreg
Definition: decode_internal.h:54
kUpb_DecodeOption_AliasString
@ kUpb_DecodeOption_AliasString
Definition: decode.h:47
upb_Decoder::end
const char * end
Definition: decode_internal.h:49
decode_checklimit
UPB_INLINE void decode_checklimit(upb_Decoder *d)
Definition: decode_internal.h:186
_upb_Message_AddUnknown
bool _upb_Message_AddUnknown(upb_Message *msg, const char *data, size_t len, upb_Arena *arena)
Definition: msg.c:85
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
UPB_ASSERT
#define UPB_ASSERT(expr)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:135
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
upb_Decoder::debug_tagstart
const char * debug_tagstart
Definition: decode_internal.h:65
d
static const fe d
Definition: curve25519_tables.h:19
upb_Message
void upb_Message
Definition: msg.h:49
setup.idx
idx
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:197
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
fastdecode_err
const char * fastdecode_err(upb_Decoder *d, int status)
Definition: decode.c:197
upb_Decoder::limit_ptr
const char * limit_ptr
Definition: decode_internal.h:50
decode_isdonefallback_inl
const UPB_INLINE char * decode_isdonefallback_inl(upb_Decoder *d, const char *ptr, int overrun, int *status)
Definition: decode_internal.h:120
upb_Decoder::end_group
uint32_t end_group
Definition: decode_internal.h:57
upb_Decoder::arena
upb_Arena arena
Definition: decode_internal.h:61
upb_Decoder::debug_valstart
const char * debug_valstart
Definition: decode_internal.h:66
upb_utf8_offsets
const uint8_t upb_utf8_offsets[]
Definition: php-upb.c:421
UPB_LIKELY
#define UPB_LIKELY(x)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:61
upb_Decoder
struct upb_Decoder upb_Decoder
kUpb_DecodeStatus_OutOfMemory
@ kUpb_DecodeStatus_OutOfMemory
Definition: decode.h:74
upb_Decoder::limit
int limit
Definition: decode_internal.h:55
decode_verifyutf8_inl
UPB_INLINE bool decode_verifyutf8_inl(const char *ptr, int len)
Definition: decode_internal.h:82
table
uint8_t table[256]
Definition: hpack_parser.cc:456
decode_totablep
const UPB_INLINE upb_MiniTable * decode_totablep(intptr_t table)
Definition: decode_internal.h:115
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
run_grpclb_interop_tests.l
dictionary l
Definition: run_grpclb_interop_tests.py:410
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
_upb_FastTable_Entry::field_parser
_upb_FieldParser * field_parser
Definition: msg_internal.h:133
upb_Decoder::err
jmp_buf err
Definition: decode_internal.h:62
msg_internal.h
upb_Arena
Definition: upb_internal.h:36
upb_Decoder::options
uint16_t options
Definition: decode_internal.h:58
decode_totable
UPB_INLINE intptr_t decode_totable(const upb_MiniTable *tablep)
Definition: decode_internal.h:111
upb_ExtensionRegistry
Definition: msg.c:372
utf8_range.h
decode_isdone
UPB_INLINE bool decode_isdone(upb_Decoder *d, const char **ptr)
Definition: decode_internal.h:151
UPB_MUSTTAIL
#define UPB_MUSTTAIL
Definition: php-upb.c:181


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:59:02