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 // We encode backwards, to avoid pre-computing lengths (one-pass encode).
29 
30 #include "upb/wire/encode.h"
31 
32 #include <string.h>
33 
34 #include "upb/collections/array_internal.h"
35 #include "upb/collections/map_sorter_internal.h"
36 #include "upb/message/extension_internal.h"
37 #include "upb/mini_table/sub_internal.h"
38 #include "upb/wire/common.h"
39 #include "upb/wire/common_internal.h"
40 #include "upb/wire/swap_internal.h"
41 #include "upb/wire/types.h"
42 
43 // Must be last.
44 #include "upb/port/def.inc"
45 
46 #define UPB_PB_VARINT_MAX_LEN 10
47 
48 UPB_NOINLINE
encode_varint64(uint64_t val,char * buf)49 static size_t encode_varint64(uint64_t val, char* buf) {
50   size_t i = 0;
51   do {
52     uint8_t byte = val & 0x7fU;
53     val >>= 7;
54     if (val) byte |= 0x80U;
55     buf[i++] = byte;
56   } while (val);
57   return i;
58 }
59 
encode_zz32(int32_t n)60 static uint32_t encode_zz32(int32_t n) {
61   return ((uint32_t)n << 1) ^ (n >> 31);
62 }
encode_zz64(int64_t n)63 static uint64_t encode_zz64(int64_t n) {
64   return ((uint64_t)n << 1) ^ (n >> 63);
65 }
66 
67 typedef struct {
68   upb_EncodeStatus status;
69   jmp_buf err;
70   upb_Arena* arena;
71   char *buf, *ptr, *limit;
72   int options;
73   int depth;
74   _upb_mapsorter sorter;
75 } upb_encstate;
76 
upb_roundup_pow2(size_t bytes)77 static size_t upb_roundup_pow2(size_t bytes) {
78   size_t ret = 128;
79   while (ret < bytes) {
80     ret *= 2;
81   }
82   return ret;
83 }
84 
encode_err(upb_encstate * e,upb_EncodeStatus s)85 UPB_NORETURN static void encode_err(upb_encstate* e, upb_EncodeStatus s) {
86   UPB_ASSERT(s != kUpb_EncodeStatus_Ok);
87   e->status = s;
88   UPB_LONGJMP(e->err, 1);
89 }
90 
91 UPB_NOINLINE
encode_growbuffer(upb_encstate * e,size_t bytes)92 static void encode_growbuffer(upb_encstate* e, size_t bytes) {
93   size_t old_size = e->limit - e->buf;
94   size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
95   char* new_buf = upb_Arena_Realloc(e->arena, e->buf, old_size, new_size);
96 
97   if (!new_buf) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
98 
99   // We want previous data at the end, realloc() put it at the beginning.
100   // TODO(salo): This is somewhat inefficient since we are copying twice.
101   // Maybe create a realloc() that copies to the end of the new buffer?
102   if (old_size > 0) {
103     memmove(new_buf + new_size - old_size, e->buf, old_size);
104   }
105 
106   e->ptr = new_buf + new_size - (e->limit - e->ptr);
107   e->limit = new_buf + new_size;
108   e->buf = new_buf;
109 
110   e->ptr -= bytes;
111 }
112 
113 /* Call to ensure that at least "bytes" bytes are available for writing at
114  * e->ptr.  Returns false if the bytes could not be allocated. */
115 UPB_FORCEINLINE
encode_reserve(upb_encstate * e,size_t bytes)116 static void encode_reserve(upb_encstate* e, size_t bytes) {
117   if ((size_t)(e->ptr - e->buf) < bytes) {
118     encode_growbuffer(e, bytes);
119     return;
120   }
121 
122   e->ptr -= bytes;
123 }
124 
125 /* Writes the given bytes to the buffer, handling reserve/advance. */
encode_bytes(upb_encstate * e,const void * data,size_t len)126 static void encode_bytes(upb_encstate* e, const void* data, size_t len) {
127   if (len == 0) return; /* memcpy() with zero size is UB */
128   encode_reserve(e, len);
129   memcpy(e->ptr, data, len);
130 }
131 
encode_fixed64(upb_encstate * e,uint64_t val)132 static void encode_fixed64(upb_encstate* e, uint64_t val) {
133   val = _upb_BigEndian_Swap64(val);
134   encode_bytes(e, &val, sizeof(uint64_t));
135 }
136 
encode_fixed32(upb_encstate * e,uint32_t val)137 static void encode_fixed32(upb_encstate* e, uint32_t val) {
138   val = _upb_BigEndian_Swap32(val);
139   encode_bytes(e, &val, sizeof(uint32_t));
140 }
141 
142 UPB_NOINLINE
encode_longvarint(upb_encstate * e,uint64_t val)143 static void encode_longvarint(upb_encstate* e, uint64_t val) {
144   size_t len;
145   char* start;
146 
147   encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
148   len = encode_varint64(val, e->ptr);
149   start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
150   memmove(start, e->ptr, len);
151   e->ptr = start;
152 }
153 
154 UPB_FORCEINLINE
encode_varint(upb_encstate * e,uint64_t val)155 static void encode_varint(upb_encstate* e, uint64_t val) {
156   if (val < 128 && e->ptr != e->buf) {
157     --e->ptr;
158     *e->ptr = val;
159   } else {
160     encode_longvarint(e, val);
161   }
162 }
163 
encode_double(upb_encstate * e,double d)164 static void encode_double(upb_encstate* e, double d) {
165   uint64_t u64;
166   UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
167   memcpy(&u64, &d, sizeof(uint64_t));
168   encode_fixed64(e, u64);
169 }
170 
encode_float(upb_encstate * e,float d)171 static void encode_float(upb_encstate* e, float d) {
172   uint32_t u32;
173   UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
174   memcpy(&u32, &d, sizeof(uint32_t));
175   encode_fixed32(e, u32);
176 }
177 
encode_tag(upb_encstate * e,uint32_t field_number,uint8_t wire_type)178 static void encode_tag(upb_encstate* e, uint32_t field_number,
179                        uint8_t wire_type) {
180   encode_varint(e, (field_number << 3) | wire_type);
181 }
182 
encode_fixedarray(upb_encstate * e,const upb_Array * arr,size_t elem_size,uint32_t tag)183 static void encode_fixedarray(upb_encstate* e, const upb_Array* arr,
184                               size_t elem_size, uint32_t tag) {
185   size_t bytes = arr->size * elem_size;
186   const char* data = _upb_array_constptr(arr);
187   const char* ptr = data + bytes - elem_size;
188 
189   if (tag || !_upb_IsLittleEndian()) {
190     while (true) {
191       if (elem_size == 4) {
192         uint32_t val;
193         memcpy(&val, ptr, sizeof(val));
194         val = _upb_BigEndian_Swap32(val);
195         encode_bytes(e, &val, elem_size);
196       } else {
197         UPB_ASSERT(elem_size == 8);
198         uint64_t val;
199         memcpy(&val, ptr, sizeof(val));
200         val = _upb_BigEndian_Swap64(val);
201         encode_bytes(e, &val, elem_size);
202       }
203 
204       if (tag) encode_varint(e, tag);
205       if (ptr == data) break;
206       ptr -= elem_size;
207     }
208   } else {
209     encode_bytes(e, data, bytes);
210   }
211 }
212 
213 static void encode_message(upb_encstate* e, const upb_Message* msg,
214                            const upb_MiniTable* m, size_t* size);
215 
encode_scalar(upb_encstate * e,const void * _field_mem,const upb_MiniTableSub * subs,const upb_MiniTableField * f)216 static void encode_scalar(upb_encstate* e, const void* _field_mem,
217                           const upb_MiniTableSub* subs,
218                           const upb_MiniTableField* f) {
219   const char* field_mem = _field_mem;
220   int wire_type;
221 
222 #define CASE(ctype, type, wtype, encodeval) \
223   {                                         \
224     ctype val = *(ctype*)field_mem;         \
225     encode_##type(e, encodeval);            \
226     wire_type = wtype;                      \
227     break;                                  \
228   }
229 
230   switch (f->UPB_PRIVATE(descriptortype)) {
231     case kUpb_FieldType_Double:
232       CASE(double, double, kUpb_WireType_64Bit, val);
233     case kUpb_FieldType_Float:
234       CASE(float, float, kUpb_WireType_32Bit, val);
235     case kUpb_FieldType_Int64:
236     case kUpb_FieldType_UInt64:
237       CASE(uint64_t, varint, kUpb_WireType_Varint, val);
238     case kUpb_FieldType_UInt32:
239       CASE(uint32_t, varint, kUpb_WireType_Varint, val);
240     case kUpb_FieldType_Int32:
241     case kUpb_FieldType_Enum:
242       CASE(int32_t, varint, kUpb_WireType_Varint, (int64_t)val);
243     case kUpb_FieldType_SFixed64:
244     case kUpb_FieldType_Fixed64:
245       CASE(uint64_t, fixed64, kUpb_WireType_64Bit, val);
246     case kUpb_FieldType_Fixed32:
247     case kUpb_FieldType_SFixed32:
248       CASE(uint32_t, fixed32, kUpb_WireType_32Bit, val);
249     case kUpb_FieldType_Bool:
250       CASE(bool, varint, kUpb_WireType_Varint, val);
251     case kUpb_FieldType_SInt32:
252       CASE(int32_t, varint, kUpb_WireType_Varint, encode_zz32(val));
253     case kUpb_FieldType_SInt64:
254       CASE(int64_t, varint, kUpb_WireType_Varint, encode_zz64(val));
255     case kUpb_FieldType_String:
256     case kUpb_FieldType_Bytes: {
257       upb_StringView view = *(upb_StringView*)field_mem;
258       encode_bytes(e, view.data, view.size);
259       encode_varint(e, view.size);
260       wire_type = kUpb_WireType_Delimited;
261       break;
262     }
263     case kUpb_FieldType_Group: {
264       size_t size;
265       void* submsg = *(void**)field_mem;
266       const upb_MiniTable* subm = subs[f->UPB_PRIVATE(submsg_index)].submsg;
267       if (submsg == NULL) {
268         return;
269       }
270       if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
271       encode_tag(e, f->number, kUpb_WireType_EndGroup);
272       encode_message(e, submsg, subm, &size);
273       wire_type = kUpb_WireType_StartGroup;
274       e->depth++;
275       break;
276     }
277     case kUpb_FieldType_Message: {
278       size_t size;
279       void* submsg = *(void**)field_mem;
280       const upb_MiniTable* subm = subs[f->UPB_PRIVATE(submsg_index)].submsg;
281       if (submsg == NULL) {
282         return;
283       }
284       if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
285       encode_message(e, submsg, subm, &size);
286       encode_varint(e, size);
287       wire_type = kUpb_WireType_Delimited;
288       e->depth++;
289       break;
290     }
291     default:
292       UPB_UNREACHABLE();
293   }
294 #undef CASE
295 
296   encode_tag(e, f->number, wire_type);
297 }
298 
encode_array(upb_encstate * e,const upb_Message * msg,const upb_MiniTableSub * subs,const upb_MiniTableField * f)299 static void encode_array(upb_encstate* e, const upb_Message* msg,
300                          const upb_MiniTableSub* subs,
301                          const upb_MiniTableField* f) {
302   const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
303   bool packed = f->mode & kUpb_LabelFlags_IsPacked;
304   size_t pre_len = e->limit - e->ptr;
305 
306   if (arr == NULL || arr->size == 0) {
307     return;
308   }
309 
310 #define VARINT_CASE(ctype, encode)                                       \
311   {                                                                      \
312     const ctype* start = _upb_array_constptr(arr);                       \
313     const ctype* ptr = start + arr->size;                                \
314     uint32_t tag = packed ? 0 : (f->number << 3) | kUpb_WireType_Varint; \
315     do {                                                                 \
316       ptr--;                                                             \
317       encode_varint(e, encode);                                          \
318       if (tag) encode_varint(e, tag);                                    \
319     } while (ptr != start);                                              \
320   }                                                                      \
321   break;
322 
323 #define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
324 
325   switch (f->UPB_PRIVATE(descriptortype)) {
326     case kUpb_FieldType_Double:
327       encode_fixedarray(e, arr, sizeof(double), TAG(kUpb_WireType_64Bit));
328       break;
329     case kUpb_FieldType_Float:
330       encode_fixedarray(e, arr, sizeof(float), TAG(kUpb_WireType_32Bit));
331       break;
332     case kUpb_FieldType_SFixed64:
333     case kUpb_FieldType_Fixed64:
334       encode_fixedarray(e, arr, sizeof(uint64_t), TAG(kUpb_WireType_64Bit));
335       break;
336     case kUpb_FieldType_Fixed32:
337     case kUpb_FieldType_SFixed32:
338       encode_fixedarray(e, arr, sizeof(uint32_t), TAG(kUpb_WireType_32Bit));
339       break;
340     case kUpb_FieldType_Int64:
341     case kUpb_FieldType_UInt64:
342       VARINT_CASE(uint64_t, *ptr);
343     case kUpb_FieldType_UInt32:
344       VARINT_CASE(uint32_t, *ptr);
345     case kUpb_FieldType_Int32:
346     case kUpb_FieldType_Enum:
347       VARINT_CASE(int32_t, (int64_t)*ptr);
348     case kUpb_FieldType_Bool:
349       VARINT_CASE(bool, *ptr);
350     case kUpb_FieldType_SInt32:
351       VARINT_CASE(int32_t, encode_zz32(*ptr));
352     case kUpb_FieldType_SInt64:
353       VARINT_CASE(int64_t, encode_zz64(*ptr));
354     case kUpb_FieldType_String:
355     case kUpb_FieldType_Bytes: {
356       const upb_StringView* start = _upb_array_constptr(arr);
357       const upb_StringView* ptr = start + arr->size;
358       do {
359         ptr--;
360         encode_bytes(e, ptr->data, ptr->size);
361         encode_varint(e, ptr->size);
362         encode_tag(e, f->number, kUpb_WireType_Delimited);
363       } while (ptr != start);
364       return;
365     }
366     case kUpb_FieldType_Group: {
367       const void* const* start = _upb_array_constptr(arr);
368       const void* const* ptr = start + arr->size;
369       const upb_MiniTable* subm = subs[f->UPB_PRIVATE(submsg_index)].submsg;
370       if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
371       do {
372         size_t size;
373         ptr--;
374         encode_tag(e, f->number, kUpb_WireType_EndGroup);
375         encode_message(e, *ptr, subm, &size);
376         encode_tag(e, f->number, kUpb_WireType_StartGroup);
377       } while (ptr != start);
378       e->depth++;
379       return;
380     }
381     case kUpb_FieldType_Message: {
382       const void* const* start = _upb_array_constptr(arr);
383       const void* const* ptr = start + arr->size;
384       const upb_MiniTable* subm = subs[f->UPB_PRIVATE(submsg_index)].submsg;
385       if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
386       do {
387         size_t size;
388         ptr--;
389         encode_message(e, *ptr, subm, &size);
390         encode_varint(e, size);
391         encode_tag(e, f->number, kUpb_WireType_Delimited);
392       } while (ptr != start);
393       e->depth++;
394       return;
395     }
396   }
397 #undef VARINT_CASE
398 
399   if (packed) {
400     encode_varint(e, e->limit - e->ptr - pre_len);
401     encode_tag(e, f->number, kUpb_WireType_Delimited);
402   }
403 }
404 
encode_mapentry(upb_encstate * e,uint32_t number,const upb_MiniTable * layout,const upb_MapEntry * ent)405 static void encode_mapentry(upb_encstate* e, uint32_t number,
406                             const upb_MiniTable* layout,
407                             const upb_MapEntry* ent) {
408   const upb_MiniTableField* key_field = &layout->fields[0];
409   const upb_MiniTableField* val_field = &layout->fields[1];
410   size_t pre_len = e->limit - e->ptr;
411   size_t size;
412   encode_scalar(e, &ent->data.v, layout->subs, val_field);
413   encode_scalar(e, &ent->data.k, layout->subs, key_field);
414   size = (e->limit - e->ptr) - pre_len;
415   encode_varint(e, size);
416   encode_tag(e, number, kUpb_WireType_Delimited);
417 }
418 
encode_map(upb_encstate * e,const upb_Message * msg,const upb_MiniTableSub * subs,const upb_MiniTableField * f)419 static void encode_map(upb_encstate* e, const upb_Message* msg,
420                        const upb_MiniTableSub* subs,
421                        const upb_MiniTableField* f) {
422   const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*);
423   const upb_MiniTable* layout = subs[f->UPB_PRIVATE(submsg_index)].submsg;
424   UPB_ASSERT(layout->field_count == 2);
425 
426   if (map == NULL) return;
427 
428   if (e->options & kUpb_EncodeOption_Deterministic) {
429     _upb_sortedmap sorted;
430     _upb_mapsorter_pushmap(&e->sorter,
431                            layout->fields[0].UPB_PRIVATE(descriptortype), map,
432                            &sorted);
433     upb_MapEntry ent;
434     while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
435       encode_mapentry(e, f->number, layout, &ent);
436     }
437     _upb_mapsorter_popmap(&e->sorter, &sorted);
438   } else {
439     intptr_t iter = UPB_STRTABLE_BEGIN;
440     upb_StringView key;
441     upb_value val;
442     while (upb_strtable_next2(&map->table, &key, &val, &iter)) {
443       upb_MapEntry ent;
444       _upb_map_fromkey(key, &ent.data.k, map->key_size);
445       _upb_map_fromvalue(val, &ent.data.v, map->val_size);
446       encode_mapentry(e, f->number, layout, &ent);
447     }
448   }
449 }
450 
encode_shouldencode(upb_encstate * e,const upb_Message * msg,const upb_MiniTableSub * subs,const upb_MiniTableField * f)451 static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
452                                 const upb_MiniTableSub* subs,
453                                 const upb_MiniTableField* f) {
454   if (f->presence == 0) {
455     /* Proto3 presence or map/array. */
456     const void* mem = UPB_PTR_AT(msg, f->offset, void);
457     switch (_upb_MiniTableField_GetRep(f)) {
458       case kUpb_FieldRep_1Byte: {
459         char ch;
460         memcpy(&ch, mem, 1);
461         return ch != 0;
462       }
463       case kUpb_FieldRep_4Byte: {
464         uint32_t u32;
465         memcpy(&u32, mem, 4);
466         return u32 != 0;
467       }
468       case kUpb_FieldRep_8Byte: {
469         uint64_t u64;
470         memcpy(&u64, mem, 8);
471         return u64 != 0;
472       }
473       case kUpb_FieldRep_StringView: {
474         const upb_StringView* str = (const upb_StringView*)mem;
475         return str->size != 0;
476       }
477       default:
478         UPB_UNREACHABLE();
479     }
480   } else if (f->presence > 0) {
481     /* Proto2 presence: hasbit. */
482     return _upb_hasbit_field(msg, f);
483   } else {
484     /* Field is in a oneof. */
485     return _upb_getoneofcase_field(msg, f) == f->number;
486   }
487 }
488 
encode_field(upb_encstate * e,const upb_Message * msg,const upb_MiniTableSub * subs,const upb_MiniTableField * field)489 static void encode_field(upb_encstate* e, const upb_Message* msg,
490                          const upb_MiniTableSub* subs,
491                          const upb_MiniTableField* field) {
492   switch (upb_FieldMode_Get(field)) {
493     case kUpb_FieldMode_Array:
494       encode_array(e, msg, subs, field);
495       break;
496     case kUpb_FieldMode_Map:
497       encode_map(e, msg, subs, field);
498       break;
499     case kUpb_FieldMode_Scalar:
500       encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
501       break;
502     default:
503       UPB_UNREACHABLE();
504   }
505 }
506 
encode_msgset_item(upb_encstate * e,const upb_Message_Extension * ext)507 static void encode_msgset_item(upb_encstate* e,
508                                const upb_Message_Extension* ext) {
509   size_t size;
510   encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup);
511   encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
512   encode_varint(e, size);
513   encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited);
514   encode_varint(e, ext->ext->field.number);
515   encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint);
516   encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup);
517 }
518 
encode_ext(upb_encstate * e,const upb_Message_Extension * ext,bool is_message_set)519 static void encode_ext(upb_encstate* e, const upb_Message_Extension* ext,
520                        bool is_message_set) {
521   if (UPB_UNLIKELY(is_message_set)) {
522     encode_msgset_item(e, ext);
523   } else {
524     encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
525   }
526 }
527 
encode_message(upb_encstate * e,const upb_Message * msg,const upb_MiniTable * m,size_t * size)528 static void encode_message(upb_encstate* e, const upb_Message* msg,
529                            const upb_MiniTable* m, size_t* size) {
530   size_t pre_len = e->limit - e->ptr;
531 
532   if ((e->options & kUpb_EncodeOption_CheckRequired) && m->required_count) {
533     uint64_t msg_head;
534     memcpy(&msg_head, msg, 8);
535     msg_head = _upb_BigEndian_Swap64(msg_head);
536     if (upb_MiniTable_requiredmask(m) & ~msg_head) {
537       encode_err(e, kUpb_EncodeStatus_MissingRequired);
538     }
539   }
540 
541   if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) {
542     size_t unknown_size;
543     const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
544 
545     if (unknown) {
546       encode_bytes(e, unknown, unknown_size);
547     }
548   }
549 
550   if (m->ext != kUpb_ExtMode_NonExtendable) {
551     /* Encode all extensions together. Unlike C++, we do not attempt to keep
552      * these in field number order relative to normal fields or even to each
553      * other. */
554     size_t ext_count;
555     const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &ext_count);
556     if (ext_count) {
557       if (e->options & kUpb_EncodeOption_Deterministic) {
558         _upb_sortedmap sorted;
559         _upb_mapsorter_pushexts(&e->sorter, ext, ext_count, &sorted);
560         while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) {
561           encode_ext(e, ext, m->ext == kUpb_ExtMode_IsMessageSet);
562         }
563         _upb_mapsorter_popmap(&e->sorter, &sorted);
564       } else {
565         const upb_Message_Extension* end = ext + ext_count;
566         for (; ext != end; ext++) {
567           encode_ext(e, ext, m->ext == kUpb_ExtMode_IsMessageSet);
568         }
569       }
570     }
571   }
572 
573   if (m->field_count) {
574     const upb_MiniTableField* f = &m->fields[m->field_count];
575     const upb_MiniTableField* first = &m->fields[0];
576     while (f != first) {
577       f--;
578       if (encode_shouldencode(e, msg, m->subs, f)) {
579         encode_field(e, msg, m->subs, f);
580       }
581     }
582   }
583 
584   *size = (e->limit - e->ptr) - pre_len;
585 }
586 
upb_Encoder_Encode(upb_encstate * const encoder,const void * const msg,const upb_MiniTable * const l,char ** const buf,size_t * const size)587 static upb_EncodeStatus upb_Encoder_Encode(upb_encstate* const encoder,
588                                            const void* const msg,
589                                            const upb_MiniTable* const l,
590                                            char** const buf,
591                                            size_t* const size) {
592   // Unfortunately we must continue to perform hackery here because there are
593   // code paths which blindly copy the returned pointer without bothering to
594   // check for errors until much later (b/235839510). So we still set *buf to
595   // NULL on error and we still set it to non-NULL on a successful empty result.
596   if (UPB_SETJMP(encoder->err) == 0) {
597     encode_message(encoder, msg, l, size);
598     *size = encoder->limit - encoder->ptr;
599     if (*size == 0) {
600       static char ch;
601       *buf = &ch;
602     } else {
603       UPB_ASSERT(encoder->ptr);
604       *buf = encoder->ptr;
605     }
606   } else {
607     UPB_ASSERT(encoder->status != kUpb_EncodeStatus_Ok);
608     *buf = NULL;
609     *size = 0;
610   }
611 
612   _upb_mapsorter_destroy(&encoder->sorter);
613   return encoder->status;
614 }
615 
upb_Encode(const void * msg,const upb_MiniTable * l,int options,upb_Arena * arena,char ** buf,size_t * size)616 upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
617                             int options, upb_Arena* arena, char** buf,
618                             size_t* size) {
619   upb_encstate e;
620   unsigned depth = (unsigned)options >> 16;
621 
622   e.status = kUpb_EncodeStatus_Ok;
623   e.arena = arena;
624   e.buf = NULL;
625   e.limit = NULL;
626   e.ptr = NULL;
627   e.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit;
628   e.options = options;
629   _upb_mapsorter_init(&e.sorter);
630 
631   return upb_Encoder_Encode(&e, msg, l, buf, size);
632 }
633