• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 //
31 #include <php.h>
32 #include <Zend/zend_exceptions.h>
33 
34 #include "protobuf.h"
35 #include "utf8.h"
36 
37 /* stringsink *****************************************************************/
38 
stringsink_start(void * _sink,const void * hd,size_t size_hint)39 static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
40   stringsink *sink = _sink;
41   sink->len = 0;
42   return sink;
43 }
44 
stringsink_string(void * _sink,const void * hd,const char * ptr,size_t len,const upb_bufhandle * handle)45 size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
46                          size_t len, const upb_bufhandle *handle) {
47   stringsink *sink = _sink;
48   size_t new_size = sink->size;
49 
50   UPB_UNUSED(hd);
51   UPB_UNUSED(handle);
52 
53   while (sink->len + len > new_size) {
54     new_size *= 2;
55   }
56 
57   if (new_size != sink->size) {
58     sink->ptr = realloc(sink->ptr, new_size);
59     sink->size = new_size;
60   }
61 
62   memcpy(sink->ptr + sink->len, ptr, len);
63   sink->len += len;
64 
65   return len;
66 }
67 
stringsink_init(stringsink * sink)68 void stringsink_init(stringsink *sink) {
69   upb_byteshandler_init(&sink->handler);
70   upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
71   upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
72 
73   upb_bytessink_reset(&sink->sink, &sink->handler, sink);
74 
75   sink->size = 32;
76   sink->ptr = malloc(sink->size);
77   sink->len = 0;
78 }
79 
stringsink_uninit(stringsink * sink)80 void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
81 
stringsink_uninit_opaque(void * sink)82 void stringsink_uninit_opaque(void *sink) { stringsink_uninit(sink); }
83 
84 /* stackenv *****************************************************************/
85 
86 // Stack-allocated context during an encode/decode operation. Contains the upb
87 // environment and its stack-based allocator, an initial buffer for allocations
88 // to avoid malloc() when possible, and a template for PHP exception messages
89 // if any error occurs.
90 #define STACK_ENV_STACKBYTES 4096
91 typedef struct {
92   upb_arena *arena;
93   upb_status status;
94   const char *php_error_template;
95   char allocbuf[STACK_ENV_STACKBYTES];
96 } stackenv;
97 
98 
99 static void stackenv_init(stackenv* se, const char* errmsg);
100 static void stackenv_uninit(stackenv* se);
101 
stackenv_init(stackenv * se,const char * errmsg)102 static void stackenv_init(stackenv* se, const char* errmsg) {
103   se->php_error_template = errmsg;
104   se->arena = upb_arena_new();
105   upb_status_clear(&se->status);
106 }
107 
stackenv_uninit(stackenv * se)108 static void stackenv_uninit(stackenv* se) {
109   upb_arena_free(se->arena);
110 
111   if (!upb_ok(&se->status)) {
112     // TODO(teboring): have a way to verify that this is actually a parse error,
113     // instead of just throwing "parse error" unconditionally.
114     TSRMLS_FETCH();
115     zend_throw_exception_ex(NULL, 0 TSRMLS_CC, se->php_error_template,
116                             upb_status_errmsg(&se->status));
117   }
118 }
119 
120 // -----------------------------------------------------------------------------
121 // Parsing.
122 // -----------------------------------------------------------------------------
123 
124 // TODO(teboring): This shoud be a bit in upb_msgdef
is_wrapper_msg(const upb_msgdef * msg)125 static bool is_wrapper_msg(const upb_msgdef *msg) {
126   return !strcmp(upb_filedef_name(upb_msgdef_file(msg)),
127                  "google/protobuf/wrappers.proto");
128 }
129 
130 #define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
131 
132 // Creates a handlerdata that simply contains the offset for this field.
newhandlerdata(upb_handlers * h,uint32_t ofs)133 static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
134   size_t* hd_ofs = (size_t*)malloc(sizeof(size_t));
135   *hd_ofs = ofs;
136   upb_handlers_addcleanup(h, hd_ofs, free);
137   return hd_ofs;
138 }
139 
140 typedef struct {
141   void* closure;
142   stringsink sink;
143 } stringfields_parseframe_t;
144 
145 typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd,
146                                             const char* ptr, size_t len,
147                                             const upb_bufhandle* handle);
148 
149 typedef struct {
150   encodeunknown_handlerfunc handler;
151 } unknownfields_handlerdata_t;
152 
153 // Creates a handlerdata for unknown fields.
newunknownfieldshandlerdata(upb_handlers * h)154 static const void *newunknownfieldshandlerdata(upb_handlers* h) {
155   unknownfields_handlerdata_t* hd =
156       (unknownfields_handlerdata_t*)malloc(sizeof(unknownfields_handlerdata_t));
157   hd->handler = stringsink_string;
158   upb_handlers_addcleanup(h, hd, free);
159   return hd;
160 }
161 
162 typedef struct {
163   size_t ofs;
164   const upb_msgdef *md;
165 } submsg_handlerdata_t;
166 
167 // Creates a handlerdata that contains offset and submessage type information.
newsubmsghandlerdata(upb_handlers * h,uint32_t ofs,const upb_fielddef * f)168 static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
169                                         const upb_fielddef* f) {
170   submsg_handlerdata_t* hd =
171       (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t));
172   hd->ofs = ofs;
173   hd->md = upb_fielddef_msgsubdef(f);
174   upb_handlers_addcleanup(h, hd, free);
175   return hd;
176 }
177 
178 typedef struct {
179   size_t ofs;              // union data slot
180   size_t case_ofs;         // oneof_case field
181   int property_ofs;        // properties table cache
182   uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
183   const upb_msgdef *md;    // msgdef, for oneof submessage handler
184   const upb_msgdef *parent_md;  // msgdef, for parent submessage
185 } oneof_handlerdata_t;
186 
newoneofhandlerdata(upb_handlers * h,uint32_t ofs,uint32_t case_ofs,int property_ofs,const upb_msgdef * m,const upb_fielddef * f)187 static const void *newoneofhandlerdata(upb_handlers *h,
188                                        uint32_t ofs,
189                                        uint32_t case_ofs,
190                                        int property_ofs,
191                                        const upb_msgdef *m,
192                                        const upb_fielddef *f) {
193   oneof_handlerdata_t* hd =
194       (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t));
195   hd->ofs = ofs;
196   hd->case_ofs = case_ofs;
197   hd->property_ofs = property_ofs;
198   hd->parent_md = m;
199   // We reuse the field tag number as a oneof union discriminant tag. Note that
200   // we don't expose these numbers to the user, so the only requirement is that
201   // we have some unique ID for each union case/possibility. The field tag
202   // numbers are already present and are easy to use so there's no reason to
203   // create a separate ID space. In addition, using the field tag number here
204   // lets us easily look up the field in the oneof accessor.
205   hd->oneof_case_num = upb_fielddef_number(f);
206   if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
207     hd->md = upb_fielddef_msgsubdef(f);
208   } else {
209     hd->md = NULL;
210   }
211   upb_handlers_addcleanup(h, hd, free);
212   return hd;
213 }
214 
215 // A handler that starts a repeated field.  Gets the Repeated*Field instance for
216 // this field (such an instance always exists even in an empty message).
startseq_handler(void * closure,const void * hd)217 static void *startseq_handler(void* closure, const void* hd) {
218   MessageHeader* msg = closure;
219   const size_t *ofs = hd;
220   return CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
221 }
222 
223 // Handlers that append primitive values to a repeated field.
224 #define DEFINE_APPEND_HANDLER(type, ctype)                          \
225   static bool append##type##_handler(void* closure, const void* hd, \
226                                      ctype val) {                   \
227     zval* array = (zval*)closure;                                   \
228     TSRMLS_FETCH();                                                 \
229     RepeatedField* intern = UNBOX(RepeatedField, array);            \
230     repeated_field_push_native(intern, &val);                       \
231     return true;                                                    \
232   }
233 
DEFINE_APPEND_HANDLER(bool,bool)234 DEFINE_APPEND_HANDLER(bool,   bool)
235 DEFINE_APPEND_HANDLER(int32,  int32_t)
236 DEFINE_APPEND_HANDLER(uint32, uint32_t)
237 DEFINE_APPEND_HANDLER(float,  float)
238 DEFINE_APPEND_HANDLER(int64,  int64_t)
239 DEFINE_APPEND_HANDLER(uint64, uint64_t)
240 DEFINE_APPEND_HANDLER(double, double)
241 
242 // Appends a string or 'bytes' string to a repeated field.
243 static void* appendstr_handler(void *closure,
244                                const void *hd,
245                                size_t size_hint) {
246   UPB_UNUSED(hd);
247 
248   stringfields_parseframe_t* frame =
249       (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
250   frame->closure = closure;
251   stringsink_init(&frame->sink);
252 
253   return frame;
254 }
255 
appendstr_end_handler(void * closure,const void * hd)256 static bool appendstr_end_handler(void *closure, const void *hd) {
257   stringfields_parseframe_t* frame = closure;
258 
259   zval* array = (zval*)frame->closure;
260   TSRMLS_FETCH();
261   RepeatedField* intern = UNBOX(RepeatedField, array);
262 
263 #if PHP_MAJOR_VERSION < 7
264   zval* str;
265   MAKE_STD_ZVAL(str);
266   PHP_PROTO_ZVAL_STRINGL(str, frame->sink.ptr, frame->sink.len, 1);
267   repeated_field_push_native(intern, &str);
268 #else
269   zend_string* str = zend_string_init(frame->sink.ptr, frame->sink.len, 1);
270   repeated_field_push_native(intern, &str);
271 #endif
272 
273   stringsink_uninit(&frame->sink);
274   free(frame);
275 
276   return true;
277 }
278 
279 // Handlers that append primitive values to a repeated field.
280 #define DEFINE_SINGULAR_HANDLER(type, ctype)                \
281   static bool type##_handler(void* closure, const void* hd, \
282                                      ctype val) {           \
283     MessageHeader* msg = (MessageHeader*)closure;           \
284     const size_t *ofs = hd;                                 \
285     DEREF(message_data(msg), *ofs, ctype) = val;            \
286     return true;                                            \
287   }
288 
DEFINE_SINGULAR_HANDLER(bool,bool)289 DEFINE_SINGULAR_HANDLER(bool,   bool)
290 DEFINE_SINGULAR_HANDLER(int32,  int32_t)
291 DEFINE_SINGULAR_HANDLER(uint32, uint32_t)
292 DEFINE_SINGULAR_HANDLER(float,  float)
293 DEFINE_SINGULAR_HANDLER(int64,  int64_t)
294 DEFINE_SINGULAR_HANDLER(uint64, uint64_t)
295 DEFINE_SINGULAR_HANDLER(double, double)
296 
297 #undef DEFINE_SINGULAR_HANDLER
298 
299 #if PHP_MAJOR_VERSION < 7
300 static void *empty_php_string(zval** value_ptr) {
301   SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
302   if (Z_TYPE_PP(value_ptr) == IS_STRING &&
303       !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
304     FREE(Z_STRVAL_PP(value_ptr));
305   }
306   ZVAL_EMPTY_STRING(*value_ptr);
307   return (void*)(*value_ptr);
308 }
309 #else
310 static void *empty_php_string(zval* value_ptr) {
311   if (Z_TYPE_P(value_ptr) == IS_STRING) {
312     zend_string_release(Z_STR_P(value_ptr));
313   }
314   ZVAL_EMPTY_STRING(value_ptr);
315   return value_ptr;
316 }
317 #endif
318 #if PHP_MAJOR_VERSION < 7
empty_php_string2(zval ** value_ptr)319 static void *empty_php_string2(zval** value_ptr) {
320   SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
321   if (Z_TYPE_PP(value_ptr) == IS_STRING &&
322       !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
323     FREE(Z_STRVAL_PP(value_ptr));
324   }
325   ZVAL_EMPTY_STRING(*value_ptr);
326   return (void*)(*value_ptr);
327 }
new_php_string(zval ** value_ptr,const char * str,size_t len)328 static void new_php_string(zval** value_ptr, const char* str, size_t len) {
329   SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
330   if (Z_TYPE_PP(value_ptr) == IS_STRING &&
331       !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
332     FREE(Z_STRVAL_PP(value_ptr));
333   }
334   ZVAL_EMPTY_STRING(*value_ptr);
335   ZVAL_STRINGL(*value_ptr, str, len, 1);
336 }
337 #else
empty_php_string2(zval * value_ptr)338 static void *empty_php_string2(zval* value_ptr) {
339   if (Z_TYPE_P(value_ptr) == IS_STRING) {
340     zend_string_release(Z_STR_P(value_ptr));
341   }
342   ZVAL_EMPTY_STRING(value_ptr);
343   return value_ptr;
344 }
new_php_string(zval * value_ptr,const char * str,size_t len)345 static void new_php_string(zval* value_ptr, const char* str, size_t len) {
346   if (Z_TYPE_P(value_ptr) == IS_STRING) {
347     zend_string_release(Z_STR_P(value_ptr));
348   }
349   ZVAL_NEW_STR(value_ptr, zend_string_init(str, len, 0));
350 }
351 #endif
352 
353 // Sets a non-repeated string/bytes field in a message.
str_handler(void * closure,const void * hd,size_t size_hint)354 static void* str_handler(void *closure,
355                          const void *hd,
356                          size_t size_hint) {
357   UPB_UNUSED(hd);
358 
359   stringfields_parseframe_t* frame =
360       (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
361   frame->closure = closure;
362   stringsink_init(&frame->sink);
363 
364   return frame;
365 }
366 
str_end_handler(void * closure,const void * hd)367 static bool str_end_handler(void *closure, const void *hd) {
368   stringfields_parseframe_t* frame = closure;
369   const size_t *ofs = hd;
370   MessageHeader* msg = (MessageHeader*)frame->closure;
371 
372   new_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*),
373                  frame->sink.ptr, frame->sink.len);
374 
375   stringsink_uninit(&frame->sink);
376   free(frame);
377 
378   return true;
379 }
380 
stringdata_handler(void * closure,const void * hd,const char * str,size_t len,const upb_bufhandle * handle)381 static size_t stringdata_handler(void* closure, const void* hd,
382                                  const char* str, size_t len,
383                                  const upb_bufhandle* handle) {
384   stringfields_parseframe_t* frame = closure;
385   return stringsink_string(&frame->sink, hd, str, len, handle);
386 }
387 
388 // Appends a submessage to a repeated field.
appendsubmsg_handler(void * closure,const void * hd)389 static void *appendsubmsg_handler(void *closure, const void *hd) {
390   zval* array = (zval*)closure;
391   TSRMLS_FETCH();
392   RepeatedField* intern = UNBOX(RepeatedField, array);
393 
394   const submsg_handlerdata_t *submsgdata = hd;
395   Descriptor* subdesc =
396       UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
397   zend_class_entry* subklass = subdesc->klass;
398   MessageHeader* submsg;
399 
400 #if PHP_MAJOR_VERSION < 7
401   zval* val = NULL;
402   MAKE_STD_ZVAL(val);
403   ZVAL_OBJ(val, subklass->create_object(subklass TSRMLS_CC));
404   repeated_field_push_native(intern, &val);
405   submsg = UNBOX(MessageHeader, val);
406 #else
407   zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
408   repeated_field_push_native(intern, &obj);
409   submsg = (MessageHeader*)((char*)obj - XtOffsetOf(MessageHeader, std));
410 #endif
411   custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
412 
413   return submsg;
414 }
415 
416 // Sets a non-repeated submessage field in a message.
submsg_handler(void * closure,const void * hd)417 static void *submsg_handler(void *closure, const void *hd) {
418   MessageHeader* msg = closure;
419   const submsg_handlerdata_t* submsgdata = hd;
420   TSRMLS_FETCH();
421   Descriptor* subdesc =
422       UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)submsgdata->md));
423   zend_class_entry* subklass = subdesc->klass;
424   zval* submsg_php;
425   MessageHeader* submsg;
426 
427   if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(message_data(msg), submsgdata->ofs,
428                                             CACHED_VALUE*))) == IS_NULL) {
429 #if PHP_MAJOR_VERSION < 7
430     zval val;
431     ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
432     MessageHeader* intern = UNBOX(MessageHeader, &val);
433     custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
434     REPLACE_ZVAL_VALUE(DEREF(message_data(msg), submsgdata->ofs, zval**),
435                        &val, 1);
436     zval_dtor(&val);
437 #else
438     zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
439     ZVAL_OBJ(DEREF(message_data(msg), submsgdata->ofs, zval*), obj);
440     MessageHeader* intern = UNBOX_HASHTABLE_VALUE(MessageHeader, obj);
441     custom_data_init(subklass, intern PHP_PROTO_TSRMLS_CC);
442 #endif
443   }
444 
445   submsg_php = CACHED_PTR_TO_ZVAL_PTR(
446       DEREF(message_data(msg), submsgdata->ofs, CACHED_VALUE*));
447 
448   submsg = UNBOX(MessageHeader, submsg_php);
449   return submsg;
450 }
451 
452 // Handler data for startmap/endmap handlers.
453 typedef struct {
454   size_t ofs;
455   upb_fieldtype_t key_field_type;
456   upb_fieldtype_t value_field_type;
457 } map_handlerdata_t;
458 
459 // Temporary frame for map parsing: at the beginning of a map entry message, a
460 // submsg handler allocates a frame to hold (i) a reference to the Map object
461 // into which this message will be inserted and (ii) storage slots to
462 // temporarily hold the key and value for this map entry until the end of the
463 // submessage. When the submessage ends, another handler is called to insert the
464 // value into the map.
465 typedef struct {
466   char key_storage[NATIVE_SLOT_MAX_SIZE];
467   char value_storage[NATIVE_SLOT_MAX_SIZE];
468 } map_parse_frame_data_t;
469 
470 PHP_PROTO_WRAP_OBJECT_START(map_parse_frame_t)
471   map_parse_frame_data_t* data;  // Place needs to be consistent with
472                                  // MessageHeader.
473   zval* map;
474   // In php7, we cannot allocate zval dynamically. So we need to add zval here
475   // to help decoding.
476   zval key_zval;
477   zval value_zval;
478 PHP_PROTO_WRAP_OBJECT_END
479 typedef struct map_parse_frame_t map_parse_frame_t;
480 
map_slot_init(void * memory,upb_fieldtype_t type,zval * cache)481 static void map_slot_init(void* memory, upb_fieldtype_t type, zval* cache) {
482   switch (type) {
483     case UPB_TYPE_STRING:
484     case UPB_TYPE_BYTES: {
485 #if PHP_MAJOR_VERSION < 7
486       // Store zval** in memory in order to be consistent with the layout of
487       // singular fields.
488       zval** holder = ALLOC(zval*);
489       *(zval***)memory = holder;
490       zval* tmp;
491       MAKE_STD_ZVAL(tmp);
492       PHP_PROTO_ZVAL_STRINGL(tmp, "", 0, 1);
493       *holder = tmp;
494 #else
495       *(zval**)memory = cache;
496       PHP_PROTO_ZVAL_STRINGL(*(zval**)memory, "", 0, 1);
497 #endif
498       break;
499     }
500     case UPB_TYPE_MESSAGE: {
501 #if PHP_MAJOR_VERSION < 7
502       zval** holder = ALLOC(zval*);
503       zval* tmp;
504       MAKE_STD_ZVAL(tmp);
505       ZVAL_NULL(tmp);
506       *holder = tmp;
507       *(zval***)memory = holder;
508 #else
509       *(zval**)memory = cache;
510       ZVAL_NULL(*(zval**)memory);
511 #endif
512       break;
513     }
514     default:
515       native_slot_init(type, memory, NULL);
516   }
517 }
518 
map_slot_uninit(void * memory,upb_fieldtype_t type)519 static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
520   switch (type) {
521     case UPB_TYPE_MESSAGE:
522     case UPB_TYPE_STRING:
523     case UPB_TYPE_BYTES: {
524 #if PHP_MAJOR_VERSION < 7
525       zval** holder = *(zval***)memory;
526       zval_ptr_dtor(holder);
527       FREE(holder);
528 #else
529       php_proto_zval_ptr_dtor(*(zval**)memory);
530 #endif
531       break;
532     }
533     default:
534       break;
535   }
536 }
537 
map_slot_key(upb_fieldtype_t type,const void * from,const char ** keyval,size_t * length)538 static void map_slot_key(upb_fieldtype_t type, const void* from,
539                          const char** keyval,
540                          size_t* length) {
541   if (type == UPB_TYPE_STRING) {
542 #if PHP_MAJOR_VERSION < 7
543     zval* key_php = **(zval***)from;
544 #else
545     zval* key_php = *(zval**)from;
546 #endif
547     *keyval = Z_STRVAL_P(key_php);
548     *length = Z_STRLEN_P(key_php);
549   } else {
550     *keyval = from;
551     *length = native_slot_size(type);
552   }
553 }
554 
map_slot_value(upb_fieldtype_t type,const void * from,upb_value * v)555 static void map_slot_value(upb_fieldtype_t type, const void* from,
556                            upb_value* v) {
557   size_t len;
558   void* to = upb_value_memory(v);
559 #ifndef NDEBUG
560   v->ctype = UPB_CTYPE_UINT64;
561 #endif
562 
563   memset(to, 0, native_slot_size(type));
564 
565   switch (type) {
566 #if PHP_MAJOR_VERSION < 7
567     case UPB_TYPE_STRING:
568     case UPB_TYPE_BYTES:
569     case UPB_TYPE_MESSAGE: {
570       *(zval**)to = **(zval***)from;
571       Z_ADDREF_PP((zval**)to);
572       break;
573     }
574 #else
575     case UPB_TYPE_STRING:
576     case UPB_TYPE_BYTES:
577       *(zend_string**)to = Z_STR_P(*(zval**)from);
578       zend_string_addref(*(zend_string**)to);
579       break;
580     case UPB_TYPE_MESSAGE:
581       *(zend_object**)to = Z_OBJ_P(*(zval**)from);
582       GC_ADDREF(*(zend_object**)to);
583       break;
584 #endif
585     default:
586       len = native_slot_size(type);
587       memcpy(to, from, len);
588   }
589 }
590 
591 // Handler to begin a map entry: allocates a temporary frame. This is the
592 // 'startsubmsg' handler on the msgdef that contains the map field.
startmapentry_handler(void * closure,const void * hd)593 static void *startmapentry_handler(void *closure, const void *hd) {
594   MessageHeader* msg = closure;
595   const map_handlerdata_t* mapdata = hd;
596   zval* map = CACHED_PTR_TO_ZVAL_PTR(
597       DEREF(message_data(msg), mapdata->ofs, CACHED_VALUE*));
598 
599   map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
600   frame->data = ALLOC(map_parse_frame_data_t);
601   frame->map = map;
602 
603   map_slot_init(&frame->data->key_storage, mapdata->key_field_type,
604                 &frame->key_zval);
605   map_slot_init(&frame->data->value_storage, mapdata->value_field_type,
606                 &frame->value_zval);
607 
608   return frame;
609 }
610 
611 // Handler to end a map entry: inserts the value defined during the message into
612 // the map. This is the 'endmsg' handler on the map entry msgdef.
endmap_handler(void * closure,const void * hd,upb_status * s)613 static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
614   map_parse_frame_t* frame = closure;
615   const map_handlerdata_t* mapdata = hd;
616 
617   TSRMLS_FETCH();
618   Map *map = UNBOX(Map, frame->map);
619 
620   const char* keyval = NULL;
621   upb_value v;
622   size_t length;
623 
624   map_slot_key(map->key_type, &frame->data->key_storage, &keyval, &length);
625   map_slot_value(map->value_type, &frame->data->value_storage, &v);
626 
627   map_index_set(map, keyval, length, v);
628 
629   map_slot_uninit(&frame->data->key_storage, mapdata->key_field_type);
630   map_slot_uninit(&frame->data->value_storage, mapdata->value_field_type);
631   FREE(frame->data);
632   FREE(frame);
633 
634   return true;
635 }
636 
637 // Allocates a new map_handlerdata_t given the map entry message definition. If
638 // the offset of the field within the parent message is also given, that is
639 // added to the handler data as well. Note that this is called *twice* per map
640 // field: once in the parent message handler setup when setting the startsubmsg
641 // handler and once in the map entry message handler setup when setting the
642 // key/value and endmsg handlers. The reason is that there is no easy way to
643 // pass the handlerdata down to the sub-message handler setup.
new_map_handlerdata(size_t ofs,const upb_msgdef * mapentry_def,Descriptor * desc)644 static map_handlerdata_t* new_map_handlerdata(
645     size_t ofs,
646     const upb_msgdef* mapentry_def,
647     Descriptor* desc) {
648   const upb_fielddef* key_field;
649   const upb_fielddef* value_field;
650   // TODO(teboring): Use emalloc and efree.
651   map_handlerdata_t* hd =
652       (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t));
653 
654   hd->ofs = ofs;
655   key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
656   assert(key_field != NULL);
657   hd->key_field_type = upb_fielddef_type(key_field);
658   value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
659   assert(value_field != NULL);
660   hd->value_field_type = upb_fielddef_type(value_field);
661 
662   return hd;
663 }
664 
665 // Handlers that set primitive values in oneofs.
666 #define DEFINE_ONEOF_HANDLER(type, ctype)                          \
667   static bool oneof##type##_handler(void* closure, const void* hd, \
668                                     ctype val) {                   \
669     const oneof_handlerdata_t* oneofdata = hd;                     \
670     MessageHeader* msg = (MessageHeader*)closure;                  \
671     DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) =  \
672         oneofdata->oneof_case_num;                                 \
673     DEREF(message_data(closure), oneofdata->ofs, ctype) = val;     \
674     return true;                                                   \
675   }
676 
DEFINE_ONEOF_HANDLER(bool,bool)677 DEFINE_ONEOF_HANDLER(bool,   bool)
678 DEFINE_ONEOF_HANDLER(int32,  int32_t)
679 DEFINE_ONEOF_HANDLER(uint32, uint32_t)
680 DEFINE_ONEOF_HANDLER(float,  float)
681 DEFINE_ONEOF_HANDLER(int64,  int64_t)
682 DEFINE_ONEOF_HANDLER(uint64, uint64_t)
683 DEFINE_ONEOF_HANDLER(double, double)
684 
685 #undef DEFINE_ONEOF_HANDLER
686 
687 static void oneof_cleanup(MessageHeader* msg,
688                           const oneof_handlerdata_t* oneofdata) {
689   uint32_t old_case_num =
690       DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
691   if (old_case_num == 0) {
692     return;
693   }
694 
695   const upb_fielddef* old_field =
696       upb_msgdef_itof(oneofdata->parent_md, old_case_num);
697   bool need_clean = false;
698 
699   switch (upb_fielddef_type(old_field)) {
700     case UPB_TYPE_STRING:
701     case UPB_TYPE_BYTES:
702       need_clean = true;
703       break;
704     case UPB_TYPE_MESSAGE:
705       if (oneofdata->oneof_case_num != old_case_num) {
706         need_clean = true;
707       }
708       break;
709     default:
710       break;
711   }
712 
713   if (need_clean) {
714 #if PHP_MAJOR_VERSION < 7
715     SEPARATE_ZVAL_IF_NOT_REF(
716         DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
717     php_proto_zval_ptr_dtor(
718         *DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
719     MAKE_STD_ZVAL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
720     ZVAL_NULL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
721 #endif
722   }
723 }
724 
725 // Handlers for string/bytes in a oneof.
oneofbytes_handler(void * closure,const void * hd,size_t size_hint)726 static void *oneofbytes_handler(void *closure,
727                                 const void *hd,
728                                 size_t size_hint) {
729   MessageHeader* msg = closure;
730   const oneof_handlerdata_t *oneofdata = hd;
731 
732   oneof_cleanup(msg, oneofdata);
733 
734   DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
735       oneofdata->oneof_case_num;
736   DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
737       OBJ_PROP(&msg->std, oneofdata->property_ofs);
738 
739    return empty_php_string(DEREF(
740        message_data(msg), oneofdata->ofs, CACHED_VALUE*));
741 }
oneofstr_end_handler(void * closure,const void * hd)742 static bool oneofstr_end_handler(void *closure, const void *hd) {
743   stringfields_parseframe_t* frame = closure;
744   MessageHeader* msg = (MessageHeader*)frame->closure;
745   const oneof_handlerdata_t *oneofdata = hd;
746 
747   oneof_cleanup(msg, oneofdata);
748 
749   DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
750       oneofdata->oneof_case_num;
751   DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
752       OBJ_PROP(&msg->std, oneofdata->property_ofs);
753 
754   new_php_string(DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*),
755                  frame->sink.ptr, frame->sink.len);
756 
757   stringsink_uninit(&frame->sink);
758   free(frame);
759 
760   return true;
761 }
762 
oneofstr_handler(void * closure,const void * hd,size_t size_hint)763 static void *oneofstr_handler(void *closure,
764                               const void *hd,
765                               size_t size_hint) {
766   UPB_UNUSED(hd);
767 
768   stringfields_parseframe_t* frame =
769       (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
770   frame->closure = closure;
771   stringsink_init(&frame->sink);
772 
773   return frame;
774 }
775 
776 // Handler for a submessage field in a oneof.
oneofsubmsg_handler(void * closure,const void * hd)777 static void* oneofsubmsg_handler(void* closure, const void* hd) {
778   MessageHeader* msg = closure;
779   const oneof_handlerdata_t *oneofdata = hd;
780   uint32_t oldcase = DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
781   TSRMLS_FETCH();
782   Descriptor* subdesc =
783       UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)oneofdata->md));
784   zend_class_entry* subklass = subdesc->klass;
785   zval* submsg_php;
786   MessageHeader* submsg;
787 
788   if (oldcase != oneofdata->oneof_case_num) {
789     oneof_cleanup(msg, oneofdata);
790 
791     // Create new message.
792     DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
793         OBJ_PROP(&msg->std, oneofdata->property_ofs);
794 #if PHP_MAJOR_VERSION < 7
795     zval val;
796     ZVAL_OBJ(&val, subklass->create_object(subklass TSRMLS_CC));
797     REPLACE_ZVAL_VALUE(DEREF(message_data(msg), oneofdata->ofs, zval**),
798                        &val, 1);
799     zval_dtor(&val);
800 #else
801     zend_object* obj = subklass->create_object(subklass TSRMLS_CC);
802     ZVAL_OBJ(DEREF(message_data(msg), oneofdata->ofs, zval*), obj);
803 #endif
804   }
805 
806   DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
807       oneofdata->oneof_case_num;
808 
809   submsg_php = CACHED_PTR_TO_ZVAL_PTR(
810       DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
811   submsg = UNBOX(MessageHeader, submsg_php);
812   custom_data_init(subklass, submsg PHP_PROTO_TSRMLS_CC);
813   return submsg;
814 }
815 
816 // Set up handlers for a repeated field.
add_handlers_for_repeated_field(upb_handlers * h,const upb_fielddef * f,size_t offset)817 static void add_handlers_for_repeated_field(upb_handlers *h,
818                                             const upb_fielddef *f,
819                                             size_t offset) {
820   upb_handlerattr attr = UPB_HANDLERATTR_INIT;
821   attr.handler_data = newhandlerdata(h, offset);
822   upb_handlers_setstartseq(h, f, startseq_handler, &attr);
823 
824   switch (upb_fielddef_type(f)) {
825 
826 #define SET_HANDLER(utype, ltype)                                 \
827   case utype:                                                     \
828     upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
829     break;
830 
831     SET_HANDLER(UPB_TYPE_BOOL,   bool);
832     SET_HANDLER(UPB_TYPE_INT32,  int32);
833     SET_HANDLER(UPB_TYPE_UINT32, uint32);
834     SET_HANDLER(UPB_TYPE_ENUM,   int32);
835     SET_HANDLER(UPB_TYPE_FLOAT,  float);
836     SET_HANDLER(UPB_TYPE_INT64,  int64);
837     SET_HANDLER(UPB_TYPE_UINT64, uint64);
838     SET_HANDLER(UPB_TYPE_DOUBLE, double);
839 
840 #undef SET_HANDLER
841 
842     case UPB_TYPE_STRING:
843     case UPB_TYPE_BYTES: {
844       upb_handlers_setstartstr(h, f, appendstr_handler, NULL);
845       upb_handlers_setstring(h, f, stringdata_handler, NULL);
846       upb_handlers_setendstr(h, f, appendstr_end_handler, &attr);
847       break;
848     }
849     case UPB_TYPE_MESSAGE: {
850       upb_handlerattr attr = UPB_HANDLERATTR_INIT;
851       attr.handler_data = newsubmsghandlerdata(h, 0, f);
852       upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
853       break;
854     }
855   }
856 }
857 
858 // Set up handlers for a singular field.
add_handlers_for_singular_field(upb_handlers * h,const upb_fielddef * f,size_t offset)859 static void add_handlers_for_singular_field(upb_handlers *h,
860                                             const upb_fielddef *f,
861                                             size_t offset) {
862   switch (upb_fielddef_type(f)) {
863 #define SET_HANDLER(utype, ltype)                          \
864   case utype: {                                            \
865     upb_handlerattr attr = UPB_HANDLERATTR_INIT;           \
866     attr.handler_data = newhandlerdata(h, offset);         \
867     upb_handlers_set##ltype(h, f, ltype##_handler, &attr); \
868     break;                                                 \
869   }
870 
871     SET_HANDLER(UPB_TYPE_BOOL,   bool);
872     SET_HANDLER(UPB_TYPE_INT32,  int32);
873     SET_HANDLER(UPB_TYPE_UINT32, uint32);
874     SET_HANDLER(UPB_TYPE_ENUM,   int32);
875     SET_HANDLER(UPB_TYPE_FLOAT,  float);
876     SET_HANDLER(UPB_TYPE_INT64,  int64);
877     SET_HANDLER(UPB_TYPE_UINT64, uint64);
878     SET_HANDLER(UPB_TYPE_DOUBLE, double);
879 
880 #undef SET_HANDLER
881 
882     case UPB_TYPE_STRING:
883     case UPB_TYPE_BYTES: {
884       upb_handlerattr attr = UPB_HANDLERATTR_INIT;
885       attr.handler_data = newhandlerdata(h, offset);
886       upb_handlers_setstartstr(h, f, str_handler, &attr);
887       upb_handlers_setstring(h, f, stringdata_handler, &attr);
888       upb_handlers_setendstr(h, f, str_end_handler, &attr);
889       break;
890     }
891     case UPB_TYPE_MESSAGE: {
892       upb_handlerattr attr = UPB_HANDLERATTR_INIT;
893       attr.handler_data = newsubmsghandlerdata(h, offset, f);
894       upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
895       break;
896     }
897   }
898 }
899 
900 // Adds handlers to a map field.
add_handlers_for_mapfield(upb_handlers * h,const upb_fielddef * fielddef,size_t offset,Descriptor * desc)901 static void add_handlers_for_mapfield(upb_handlers* h,
902                                       const upb_fielddef* fielddef,
903                                       size_t offset,
904                                       Descriptor* desc) {
905   const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
906   map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
907   upb_handlerattr attr = UPB_HANDLERATTR_INIT;
908 
909   upb_handlers_addcleanup(h, hd, free);
910   attr.handler_data = hd;
911   upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
912 }
913 
914 // Adds handlers to a map-entry msgdef.
add_handlers_for_mapentry(const upb_msgdef * msgdef,upb_handlers * h,Descriptor * desc)915 static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
916                                       Descriptor* desc) {
917   const upb_fielddef* key_field = map_entry_key(msgdef);
918   const upb_fielddef* value_field = map_entry_value(msgdef);
919   map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
920   upb_handlerattr attr = UPB_HANDLERATTR_INIT;
921 
922   upb_handlers_addcleanup(h, hd, free);
923   attr.handler_data = hd;
924   upb_handlers_setendmsg(h, endmap_handler, &attr);
925 
926   add_handlers_for_singular_field(h, key_field,
927                                   offsetof(map_parse_frame_data_t,
928                                            key_storage));
929   add_handlers_for_singular_field(h, value_field,
930                                   offsetof(map_parse_frame_data_t,
931                                            value_storage));
932 }
933 
934 // Set up handlers for a oneof field.
add_handlers_for_oneof_field(upb_handlers * h,const upb_msgdef * m,const upb_fielddef * f,size_t offset,size_t oneof_case_offset,int property_cache_offset)935 static void add_handlers_for_oneof_field(upb_handlers *h,
936                                          const upb_msgdef *m,
937                                          const upb_fielddef *f,
938                                          size_t offset,
939                                          size_t oneof_case_offset,
940                                          int property_cache_offset) {
941 
942   upb_handlerattr attr = UPB_HANDLERATTR_INIT;
943   attr.handler_data = newoneofhandlerdata(h, offset, oneof_case_offset,
944                                           property_cache_offset, m, f);
945 
946   switch (upb_fielddef_type(f)) {
947 
948 #define SET_HANDLER(utype, ltype)                                 \
949   case utype:                                                     \
950     upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
951     break;
952 
953     SET_HANDLER(UPB_TYPE_BOOL,   bool);
954     SET_HANDLER(UPB_TYPE_INT32,  int32);
955     SET_HANDLER(UPB_TYPE_UINT32, uint32);
956     SET_HANDLER(UPB_TYPE_ENUM,   int32);
957     SET_HANDLER(UPB_TYPE_FLOAT,  float);
958     SET_HANDLER(UPB_TYPE_INT64,  int64);
959     SET_HANDLER(UPB_TYPE_UINT64, uint64);
960     SET_HANDLER(UPB_TYPE_DOUBLE, double);
961 
962 #undef SET_HANDLER
963 
964     case UPB_TYPE_STRING:
965     case UPB_TYPE_BYTES: {
966       upb_handlers_setstartstr(h, f, oneofstr_handler, &attr);
967       upb_handlers_setstring(h, f, stringdata_handler, NULL);
968       upb_handlers_setendstr(h, f, oneofstr_end_handler, &attr);
969       break;
970     }
971     case UPB_TYPE_MESSAGE: {
972       upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
973       break;
974     }
975   }
976 }
977 
add_unknown_handler(void * closure,const void * hd,const char * buf,size_t size)978 static bool add_unknown_handler(void* closure, const void* hd, const char* buf,
979                          size_t size) {
980   encodeunknown_handlerfunc handler =
981       ((unknownfields_handlerdata_t*)hd)->handler;
982 
983   MessageHeader* msg = (MessageHeader*)closure;
984   stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
985   if (unknown == NULL) {
986     DEREF(message_data(msg), 0, stringsink*) = ALLOC(stringsink);
987     unknown = DEREF(message_data(msg), 0, stringsink*);
988     stringsink_init(unknown);
989   }
990 
991   handler(unknown, NULL, buf, size, NULL);
992 
993   return true;
994 }
995 
add_handlers_for_message(const void * closure,upb_handlers * h)996 void add_handlers_for_message(const void* closure, upb_handlers* h) {
997   const upb_msgdef* msgdef = upb_handlers_msgdef(h);
998   TSRMLS_FETCH();
999   Descriptor* desc =
1000       UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)msgdef));
1001   upb_msg_field_iter i;
1002 
1003   // If this is a mapentry message type, set up a special set of handlers and
1004   // bail out of the normal (user-defined) message type handling.
1005   if (upb_msgdef_mapentry(msgdef)) {
1006     add_handlers_for_mapentry(msgdef, h, desc);
1007     return;
1008   }
1009 
1010   // Ensure layout exists. We may be invoked to create handlers for a given
1011   // message if we are included as a submsg of another message type before our
1012   // class is actually built, so to work around this, we just create the layout
1013   // (and handlers, in the class-building function) on-demand.
1014   if (desc->layout == NULL) {
1015     desc->layout = create_layout(desc->msgdef);
1016   }
1017 
1018   upb_handlerattr attr = UPB_HANDLERATTR_INIT;
1019   attr.handler_data = newunknownfieldshandlerdata(h);
1020   upb_handlers_setunknown(h, add_unknown_handler, &attr);
1021 
1022   for (upb_msg_field_begin(&i, desc->msgdef);
1023        !upb_msg_field_done(&i);
1024        upb_msg_field_next(&i)) {
1025     const upb_fielddef *f = upb_msg_iter_field(&i);
1026     size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
1027 
1028     if (upb_fielddef_containingoneof(f)) {
1029       size_t oneof_case_offset =
1030           desc->layout->fields[upb_fielddef_index(f)].case_offset;
1031       int property_cache_index =
1032           desc->layout->fields[upb_fielddef_index(f)].cache_index;
1033       add_handlers_for_oneof_field(h, desc->msgdef, f, offset,
1034                                    oneof_case_offset, property_cache_index);
1035     } else if (is_map_field(f)) {
1036       add_handlers_for_mapfield(h, f, offset, desc);
1037     } else if (upb_fielddef_isseq(f)) {
1038       add_handlers_for_repeated_field(h, f, offset);
1039     } else {
1040       add_handlers_for_singular_field(h, f, offset);
1041     }
1042   }
1043 }
1044 
1045 // Constructs the handlers for filling a message's data into an in-memory
1046 // object.
get_fill_handlers(Descriptor * desc)1047 const upb_handlers* get_fill_handlers(Descriptor* desc) {
1048   return upb_handlercache_get(desc->pool->fill_handler_cache, desc->msgdef);
1049 }
1050 
msgdef_decodermethod(Descriptor * desc)1051 static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
1052   return upb_pbcodecache_get(desc->pool->fill_method_cache, desc->msgdef);
1053 }
1054 
msgdef_jsonparsermethod(Descriptor * desc)1055 static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
1056   return upb_json_codecache_get(desc->pool->json_fill_method_cache, desc->msgdef);
1057 }
1058 
1059 // -----------------------------------------------------------------------------
1060 // Serializing.
1061 // -----------------------------------------------------------------------------
1062 
1063 static void putmsg(zval* msg, const Descriptor* desc, upb_sink sink,
1064                    int depth, bool is_json TSRMLS_DC);
1065 static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
1066                       upb_sink sink, int depth, bool is_json,
1067                       bool open_msg TSRMLS_DC);
1068 static void putjsonany(MessageHeader* msg, const Descriptor* desc,
1069                        upb_sink sink, int depth TSRMLS_DC);
1070 static void putjsonlistvalue(
1071     MessageHeader* msg, const Descriptor* desc,
1072     upb_sink sink, int depth TSRMLS_DC);
1073 static void putjsonstruct(
1074     MessageHeader* msg, const Descriptor* desc,
1075     upb_sink sink, int depth TSRMLS_DC);
1076 
1077 static void putstr(zval* str, const upb_fielddef* f, upb_sink sink,
1078                    bool force_default);
1079 
1080 static void putrawstr(const char* str, int len, const upb_fielddef* f,
1081                       upb_sink sink, bool force_default);
1082 
1083 static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink sink,
1084                       int depth, bool is_json TSRMLS_DC);
1085 static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
1086                          upb_sink sink, int depth, bool is_json TSRMLS_DC);
1087 
1088 static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
1089                      int depth, bool is_json TSRMLS_DC);
1090 static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
1091                    int depth, bool is_json TSRMLS_DC);
1092 
getsel(const upb_fielddef * f,upb_handlertype_t type)1093 static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) {
1094   upb_selector_t ret;
1095   bool ok = upb_handlers_getselector(f, type, &ret);
1096   UPB_ASSERT(ok);
1097   return ret;
1098 }
1099 
put_optional_value(const void * memory,int len,const upb_fielddef * f,int depth,upb_sink sink,bool is_json TSRMLS_DC)1100 static void put_optional_value(const void* memory, int len,
1101                                const upb_fielddef* f,
1102                                int depth, upb_sink sink,
1103                                bool is_json TSRMLS_DC) {
1104   assert(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL);
1105 
1106   switch (upb_fielddef_type(f)) {
1107 #define T(upbtypeconst, upbtype, ctype, default_value)                         \
1108   case upbtypeconst: {                                                         \
1109     ctype value = DEREF(memory, 0, ctype);                                     \
1110     if (is_json || value != default_value) {                                   \
1111       upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \
1112       upb_sink_put##upbtype(sink, sel, value);                                 \
1113     }                                                                          \
1114   } break;
1115 
1116     T(UPB_TYPE_FLOAT, float, float, 0.0)
1117     T(UPB_TYPE_DOUBLE, double, double, 0.0)
1118     T(UPB_TYPE_BOOL, bool, uint8_t, 0)
1119     T(UPB_TYPE_ENUM, int32, int32_t, 0)
1120     T(UPB_TYPE_INT32, int32, int32_t, 0)
1121     T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
1122     T(UPB_TYPE_INT64, int64, int64_t, 0)
1123     T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
1124 
1125 #undef T
1126     case UPB_TYPE_STRING:
1127     case UPB_TYPE_BYTES:
1128       putrawstr(memory, len, f, sink, is_json);
1129       break;
1130     case UPB_TYPE_MESSAGE: {
1131 #if PHP_MAJOR_VERSION < 7
1132       MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
1133 #else
1134       MessageHeader *submsg =
1135           (MessageHeader*)((char*)(*(zend_object**)memory) -
1136               XtOffsetOf(MessageHeader, std));
1137 #endif
1138       putrawsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
1139       break;
1140     }
1141     default:
1142       assert(false);
1143   }
1144 }
1145 
1146 // Only string/bytes fields are stored as zval.
raw_value(void * memory,const upb_fielddef * f)1147 static const char* raw_value(void* memory, const upb_fielddef* f) {
1148   switch (upb_fielddef_type(f)) {
1149     case UPB_TYPE_STRING:
1150     case UPB_TYPE_BYTES:
1151 #if PHP_MAJOR_VERSION < 7
1152       return Z_STRVAL_PP((zval**)memory);
1153 #else
1154       return ZSTR_VAL(*(zend_string**)memory);
1155 #endif
1156       break;
1157     default:
1158       return memory;
1159   }
1160 }
1161 
raw_value_len(void * memory,int len,const upb_fielddef * f)1162 static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
1163   switch (upb_fielddef_type(f)) {
1164     case UPB_TYPE_STRING:
1165     case UPB_TYPE_BYTES:
1166 #if PHP_MAJOR_VERSION < 7
1167       return Z_STRLEN_PP((zval**)memory);
1168 #else
1169       return ZSTR_LEN(*(zend_string**)memory);
1170 #endif
1171     default:
1172       return len;
1173   }
1174 }
1175 
putmap(zval * map,const upb_fielddef * f,upb_sink sink,int depth,bool is_json TSRMLS_DC)1176 static void putmap(zval* map, const upb_fielddef* f, upb_sink sink,
1177                    int depth, bool is_json TSRMLS_DC) {
1178   upb_sink subsink;
1179   const upb_fielddef* key_field;
1180   const upb_fielddef* value_field;
1181   MapIter it;
1182   int len, size;
1183 
1184   assert(map != NULL);
1185   Map* intern = UNBOX(Map, map);
1186   size = upb_strtable_count(&intern->table);
1187   if (size == 0) return;
1188 
1189   upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1190 
1191   assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
1192   key_field = map_field_key(f);
1193   value_field = map_field_value(f);
1194 
1195   for (map_begin(map, &it TSRMLS_CC); !map_done(&it); map_next(&it)) {
1196     upb_status status;
1197 
1198     upb_sink entry_sink;
1199     upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
1200                          &entry_sink);
1201     upb_sink_startmsg(entry_sink);
1202 
1203     // Serialize key.
1204     const char *key = map_iter_key(&it, &len);
1205     put_optional_value(key, len, key_field, depth + 1,
1206                        entry_sink, is_json TSRMLS_CC);
1207 
1208     // Serialize value.
1209     upb_value value = map_iter_value(&it, &len);
1210     put_optional_value(raw_value(upb_value_memory(&value), value_field),
1211                        raw_value_len(upb_value_memory(&value), len, value_field),
1212                        value_field, depth + 1, entry_sink, is_json TSRMLS_CC);
1213 
1214     upb_sink_endmsg(entry_sink, &status);
1215     upb_sink_endsubmsg(subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1216   }
1217 
1218   upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1219 }
1220 
putmsg(zval * msg_php,const Descriptor * desc,upb_sink sink,int depth,bool is_json TSRMLS_DC)1221 static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink sink,
1222                    int depth, bool is_json TSRMLS_DC) {
1223   MessageHeader* msg = UNBOX(MessageHeader, msg_php);
1224   putrawmsg(msg, desc, sink, depth, is_json, true TSRMLS_CC);
1225 }
1226 
1227 static const upb_handlers* msgdef_json_serialize_handlers(
1228     Descriptor* desc, bool preserve_proto_fieldnames);
1229 
putjsonany(MessageHeader * msg,const Descriptor * desc,upb_sink sink,int depth TSRMLS_DC)1230 static void putjsonany(MessageHeader* msg, const Descriptor* desc,
1231                        upb_sink sink, int depth TSRMLS_DC) {
1232   upb_status status;
1233   const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
1234   const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
1235 
1236   uint32_t type_url_offset;
1237   zval* type_url_php_str;
1238   const upb_msgdef *payload_type = NULL;
1239 
1240   upb_sink_startmsg(sink);
1241 
1242   /* Handle type url */
1243   type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
1244   type_url_php_str = CACHED_PTR_TO_ZVAL_PTR(
1245       DEREF(message_data(msg), type_url_offset, CACHED_VALUE*));
1246   if (Z_STRLEN_P(type_url_php_str) > 0) {
1247     putstr(type_url_php_str, type_field, sink, false);
1248   }
1249 
1250   {
1251     const char* type_url_str = Z_STRVAL_P(type_url_php_str);
1252     size_t type_url_len = Z_STRLEN_P(type_url_php_str);
1253     if (type_url_len <= 20 ||
1254         strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
1255       zend_error(E_ERROR, "Invalid type url: %s", type_url_str);
1256     }
1257 
1258     /* Resolve type url */
1259     type_url_str += 20;
1260     type_url_len -= 20;
1261 
1262     payload_type = upb_symtab_lookupmsg2(
1263         generated_pool->symtab, type_url_str, type_url_len);
1264     if (payload_type == NULL) {
1265       zend_error(E_ERROR, "Unknown type: %s", type_url_str);
1266       return;
1267     }
1268   }
1269 
1270   {
1271     uint32_t value_offset;
1272     zval* value_php_str;
1273     const char* value_str;
1274     size_t value_len;
1275 
1276     value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
1277     value_php_str = CACHED_PTR_TO_ZVAL_PTR(
1278         DEREF(message_data(msg), value_offset, CACHED_VALUE*));
1279     value_str = Z_STRVAL_P(value_php_str);
1280     value_len = Z_STRLEN_P(value_php_str);
1281 
1282     if (value_len > 0) {
1283       Descriptor* payload_desc =
1284           UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj((void*)payload_type));
1285       zend_class_entry* payload_klass = payload_desc->klass;
1286       zval val;
1287       upb_sink subsink;
1288       bool is_wellknown;
1289 
1290       /* Create message of the payload type. */
1291       ZVAL_OBJ(&val, payload_klass->create_object(payload_klass TSRMLS_CC));
1292       MessageHeader* intern = UNBOX(MessageHeader, &val);
1293       custom_data_init(payload_klass, intern PHP_PROTO_TSRMLS_CC);
1294 
1295       merge_from_string(value_str, value_len, payload_desc, intern);
1296 
1297       is_wellknown =
1298           upb_msgdef_wellknowntype(payload_desc->msgdef) !=
1299               UPB_WELLKNOWN_UNSPECIFIED;
1300       if (is_wellknown) {
1301         upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
1302                           &subsink);
1303       }
1304 
1305       subsink.handlers =
1306           msgdef_json_serialize_handlers(payload_desc, true);
1307       subsink.closure = sink.closure;
1308       putrawmsg(intern, payload_desc, subsink, depth, true,
1309                 is_wellknown TSRMLS_CC);
1310 
1311       zval_dtor(&val);
1312     }
1313   }
1314 
1315   upb_sink_endmsg(sink, &status);
1316 }
1317 
putjsonlistvalue(MessageHeader * msg,const Descriptor * desc,upb_sink sink,int depth TSRMLS_DC)1318 static void putjsonlistvalue(
1319     MessageHeader* msg, const Descriptor* desc,
1320     upb_sink sink, int depth TSRMLS_DC) {
1321   upb_status status;
1322   upb_sink subsink;
1323   const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
1324   uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
1325   zval* array;
1326   RepeatedField* intern;
1327   HashTable *ht;
1328   int size, i;
1329 
1330   upb_sink_startmsg(sink);
1331 
1332   array = CACHED_PTR_TO_ZVAL_PTR(
1333       DEREF(message_data(msg), offset, CACHED_VALUE*));
1334   intern = UNBOX(RepeatedField, array);
1335   ht = PHP_PROTO_HASH_OF(intern->array);
1336   size = zend_hash_num_elements(ht);
1337 
1338   if (size == 0) {
1339     upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1340     upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1341   } else {
1342     putarray(array, f, sink, depth, true TSRMLS_CC);
1343   }
1344 
1345   upb_sink_endmsg(sink, &status);
1346 }
1347 
putjsonstruct(MessageHeader * msg,const Descriptor * desc,upb_sink sink,int depth TSRMLS_DC)1348 static void putjsonstruct(
1349     MessageHeader* msg, const Descriptor* desc,
1350     upb_sink sink, int depth TSRMLS_DC) {
1351   upb_status status;
1352   upb_sink subsink;
1353   const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
1354   uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
1355   zval* map;
1356   Map* intern;
1357   int size;
1358 
1359   upb_sink_startmsg(sink);
1360 
1361   map = CACHED_PTR_TO_ZVAL_PTR(
1362       DEREF(message_data(msg), offset, CACHED_VALUE*));
1363   intern = UNBOX(Map, map);
1364   size = upb_strtable_count(&intern->table);
1365 
1366   if (size == 0) {
1367     upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1368     upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1369   } else {
1370     putmap(map, f, sink, depth, true TSRMLS_CC);
1371   }
1372 
1373   upb_sink_endmsg(sink, &status);
1374 }
1375 
putrawmsg(MessageHeader * msg,const Descriptor * desc,upb_sink sink,int depth,bool is_json,bool open_msg TSRMLS_DC)1376 static void putrawmsg(MessageHeader* msg, const Descriptor* desc,
1377                       upb_sink sink, int depth, bool is_json,
1378                       bool open_msg TSRMLS_DC) {
1379   upb_msg_field_iter i;
1380   upb_status status;
1381 
1382   if (is_json &&
1383       upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
1384     putjsonany(msg, desc, sink, depth TSRMLS_CC);
1385     return;
1386   }
1387 
1388   if (is_json &&
1389       upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
1390     putjsonlistvalue(msg, desc, sink, depth TSRMLS_CC);
1391     return;
1392   }
1393 
1394   if (is_json &&
1395       upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_STRUCT) {
1396     putjsonstruct(msg, desc, sink, depth TSRMLS_CC);
1397     return;
1398   }
1399 
1400   if (open_msg) {
1401     upb_sink_startmsg(sink);
1402   }
1403 
1404   // Protect against cycles (possible because users may freely reassign message
1405   // and repeated fields) by imposing a maximum recursion depth.
1406   if (depth > ENCODE_MAX_NESTING) {
1407     zend_error(E_ERROR,
1408              "Maximum recursion depth exceeded during encoding.");
1409   }
1410 
1411   for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i);
1412        upb_msg_field_next(&i)) {
1413     upb_fielddef* f = upb_msg_iter_field(&i);
1414     uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
1415     bool containing_oneof = false;
1416 
1417     if (upb_fielddef_containingoneof(f)) {
1418       uint32_t oneof_case_offset =
1419           desc->layout->fields[upb_fielddef_index(f)].case_offset;
1420       // For a oneof, check that this field is actually present -- skip all the
1421       // below if not.
1422       if (DEREF(message_data(msg), oneof_case_offset, uint32_t) !=
1423           upb_fielddef_number(f)) {
1424         continue;
1425       }
1426       // Otherwise, fall through to the appropriate singular-field handler
1427       // below.
1428       containing_oneof = true;
1429     }
1430 
1431     if (is_map_field(f)) {
1432       zval* map = CACHED_PTR_TO_ZVAL_PTR(
1433           DEREF(message_data(msg), offset, CACHED_VALUE*));
1434       if (map != NULL) {
1435         putmap(map, f, sink, depth, is_json TSRMLS_CC);
1436       }
1437     } else if (upb_fielddef_isseq(f)) {
1438       zval* array = CACHED_PTR_TO_ZVAL_PTR(
1439           DEREF(message_data(msg), offset, CACHED_VALUE*));
1440       if (array != NULL) {
1441         putarray(array, f, sink, depth, is_json TSRMLS_CC);
1442       }
1443     } else if (upb_fielddef_isstring(f)) {
1444       zval* str = CACHED_PTR_TO_ZVAL_PTR(
1445           DEREF(message_data(msg), offset, CACHED_VALUE*));
1446       if (containing_oneof || (is_json && is_wrapper_msg(desc->msgdef)) ||
1447           Z_STRLEN_P(str) > 0) {
1448         putstr(str, f, sink, is_json && is_wrapper_msg(desc->msgdef));
1449       }
1450     } else if (upb_fielddef_issubmsg(f)) {
1451       putsubmsg(CACHED_PTR_TO_ZVAL_PTR(
1452                     DEREF(message_data(msg), offset, CACHED_VALUE*)),
1453                 f, sink, depth, is_json TSRMLS_CC);
1454     } else {
1455       upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1456 
1457 #define T(upbtypeconst, upbtype, ctype, default_value)     \
1458   case upbtypeconst: {                                     \
1459     ctype value = DEREF(message_data(msg), offset, ctype); \
1460     if (containing_oneof ||                                \
1461         (is_json && is_wrapper_msg(desc->msgdef)) ||       \
1462         value != default_value) {                          \
1463       upb_sink_put##upbtype(sink, sel, value);             \
1464     }                                                      \
1465   } break;
1466 
1467       switch (upb_fielddef_type(f)) {
1468         T(UPB_TYPE_FLOAT, float, float, 0.0)
1469         T(UPB_TYPE_DOUBLE, double, double, 0.0)
1470         T(UPB_TYPE_BOOL, bool, uint8_t, 0)
1471         case UPB_TYPE_ENUM:
1472         T(UPB_TYPE_INT32, int32, int32_t, 0)
1473         T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
1474         T(UPB_TYPE_INT64, int64, int64_t, 0)
1475         T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
1476 
1477         case UPB_TYPE_STRING:
1478         case UPB_TYPE_BYTES:
1479         case UPB_TYPE_MESSAGE:
1480           zend_error(E_ERROR, "Internal error.");
1481       }
1482 
1483 #undef T
1484     }
1485   }
1486 
1487   stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
1488   if (unknown != NULL) {
1489     upb_sink_putunknown(sink, unknown->ptr, unknown->len);
1490   }
1491 
1492   if (open_msg) {
1493     upb_sink_endmsg(sink, &status);
1494   }
1495 }
1496 
putstr(zval * str,const upb_fielddef * f,upb_sink sink,bool force_default)1497 static void putstr(zval* str, const upb_fielddef *f,
1498                    upb_sink sink, bool force_default) {
1499   upb_sink subsink;
1500 
1501   if (ZVAL_IS_NULL(str)) return;
1502 
1503   assert(Z_TYPE_P(str) == IS_STRING);
1504 
1505   upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str),
1506                     &subsink);
1507 
1508   // For oneof string field, we may get here with string length is zero.
1509   if (Z_STRLEN_P(str) > 0 || force_default) {
1510     // Ensure that the string has the correct encoding. We also check at
1511     // field-set time, but the user may have mutated the string object since
1512     // then.
1513     if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
1514         !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
1515       zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
1516       return;
1517     }
1518     upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
1519                        Z_STRLEN_P(str), NULL);
1520   }
1521 
1522   upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
1523 }
1524 
putrawstr(const char * str,int len,const upb_fielddef * f,upb_sink sink,bool force_default)1525 static void putrawstr(const char* str, int len, const upb_fielddef* f,
1526                       upb_sink sink, bool force_default) {
1527   upb_sink subsink;
1528 
1529   if (len == 0 && !force_default) return;
1530 
1531   // Ensure that the string has the correct encoding. We also check at field-set
1532   // time, but the user may have mutated the string object since then.
1533   if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
1534       !is_structurally_valid_utf8(str, len)) {
1535     zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
1536     return;
1537   }
1538 
1539   upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink);
1540   upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL);
1541   upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
1542 }
1543 
putsubmsg(zval * submsg_php,const upb_fielddef * f,upb_sink sink,int depth,bool is_json TSRMLS_DC)1544 static void putsubmsg(zval* submsg_php, const upb_fielddef* f, upb_sink sink,
1545                       int depth, bool is_json TSRMLS_DC) {
1546   if (Z_TYPE_P(submsg_php) == IS_NULL) return;
1547 
1548   MessageHeader *submsg = UNBOX(MessageHeader, submsg_php);
1549   putrawsubmsg(submsg, f, sink, depth, is_json TSRMLS_CC);
1550 }
1551 
putrawsubmsg(MessageHeader * submsg,const upb_fielddef * f,upb_sink sink,int depth,bool is_json TSRMLS_DC)1552 static void putrawsubmsg(MessageHeader* submsg, const upb_fielddef* f,
1553                          upb_sink sink, int depth, bool is_json TSRMLS_DC) {
1554   upb_sink subsink;
1555 
1556   Descriptor* subdesc =
1557       UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(upb_fielddef_msgsubdef(f)));
1558 
1559   upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
1560   putrawmsg(submsg, subdesc, subsink, depth + 1, is_json, true TSRMLS_CC);
1561   upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1562 }
1563 
putarray(zval * array,const upb_fielddef * f,upb_sink sink,int depth,bool is_json TSRMLS_DC)1564 static void putarray(zval* array, const upb_fielddef* f, upb_sink sink,
1565                      int depth, bool is_json TSRMLS_DC) {
1566   upb_sink subsink;
1567   upb_fieldtype_t type = upb_fielddef_type(f);
1568   upb_selector_t sel = 0;
1569   int size, i;
1570 
1571   assert(array != NULL);
1572   RepeatedField* intern = UNBOX(RepeatedField, array);
1573   HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
1574   size = zend_hash_num_elements(ht);
1575   if (size == 0) return;
1576 
1577   upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
1578 
1579   if (upb_fielddef_isprimitive(f)) {
1580     sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
1581   }
1582 
1583   for (i = 0; i < size; i++) {
1584     void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
1585     switch (type) {
1586 #define T(upbtypeconst, upbtype, ctype)                      \
1587   case upbtypeconst:                                         \
1588     upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
1589     break;
1590 
1591       T(UPB_TYPE_FLOAT, float, float)
1592       T(UPB_TYPE_DOUBLE, double, double)
1593       T(UPB_TYPE_BOOL, bool, int8_t)
1594       case UPB_TYPE_ENUM:
1595         T(UPB_TYPE_INT32, int32, int32_t)
1596         T(UPB_TYPE_UINT32, uint32, uint32_t)
1597         T(UPB_TYPE_INT64, int64, int64_t)
1598         T(UPB_TYPE_UINT64, uint64, uint64_t)
1599 
1600       case UPB_TYPE_STRING:
1601       case UPB_TYPE_BYTES: {
1602 #if PHP_MAJOR_VERSION < 7
1603         const char* rawstr = Z_STRVAL_P(*(zval**)memory);
1604         int len = Z_STRLEN_P(*(zval**)memory);
1605 #else
1606         const char* rawstr = ZSTR_VAL(*(zend_string**)memory);
1607         int len = ZSTR_LEN(*(zend_string**)memory);
1608 #endif
1609         putrawstr(rawstr, len, f, subsink,
1610                   is_json && is_wrapper_msg(upb_fielddef_containingtype(f)));
1611         break;
1612       }
1613       case UPB_TYPE_MESSAGE: {
1614 #if PHP_MAJOR_VERSION < 7
1615         MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
1616 #else
1617         MessageHeader *submsg =
1618             (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
1619                 XtOffsetOf(MessageHeader, std));
1620 #endif
1621         putrawsubmsg(submsg, f, subsink, depth, is_json TSRMLS_CC);
1622         break;
1623       }
1624 
1625 #undef T
1626     }
1627   }
1628   upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
1629 }
1630 
msgdef_pb_serialize_handlers(Descriptor * desc)1631 static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
1632   return upb_handlercache_get(desc->pool->pb_serialize_handler_cache,
1633                               desc->msgdef);
1634 }
1635 
msgdef_json_serialize_handlers(Descriptor * desc,bool preserve_proto_fieldnames)1636 static const upb_handlers* msgdef_json_serialize_handlers(
1637     Descriptor* desc, bool preserve_proto_fieldnames) {
1638   if (preserve_proto_fieldnames) {
1639     return upb_handlercache_get(
1640         desc->pool->json_serialize_handler_preserve_cache, desc->msgdef);
1641   } else {
1642     return upb_handlercache_get(desc->pool->json_serialize_handler_cache,
1643                                 desc->msgdef);
1644   }
1645 }
1646 
1647 // -----------------------------------------------------------------------------
1648 // PHP encode/decode methods
1649 // -----------------------------------------------------------------------------
1650 
serialize_to_string(zval * val,zval * return_value TSRMLS_DC)1651 void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
1652   Descriptor* desc =
1653       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
1654 
1655   stringsink sink;
1656   stringsink_init(&sink);
1657 
1658   {
1659     const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc);
1660 
1661     stackenv se;
1662     upb_pb_encoder* encoder;
1663 
1664     stackenv_init(&se, "Error occurred during encoding: %s");
1665     encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
1666 
1667     putmsg(val, desc, upb_pb_encoder_input(encoder), 0, false TSRMLS_CC);
1668 
1669     PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
1670 
1671     stackenv_uninit(&se);
1672     stringsink_uninit(&sink);
1673   }
1674 }
1675 
PHP_METHOD(Message,serializeToString)1676 PHP_METHOD(Message, serializeToString) {
1677   serialize_to_string(getThis(), return_value TSRMLS_CC);
1678 }
1679 
merge_from_string(const char * data,int data_len,Descriptor * desc,MessageHeader * msg)1680 void merge_from_string(const char* data, int data_len, Descriptor* desc,
1681                        MessageHeader* msg) {
1682   const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
1683   const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
1684   stackenv se;
1685   upb_sink sink;
1686   upb_pbdecoder* decoder;
1687   stackenv_init(&se, "Error occurred during parsing: %s");
1688 
1689   upb_sink_reset(&sink, h, msg);
1690   decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
1691   upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
1692 
1693   stackenv_uninit(&se);
1694 }
1695 
PHP_METHOD(Message,mergeFromString)1696 PHP_METHOD(Message, mergeFromString) {
1697   Descriptor* desc =
1698       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
1699   MessageHeader* msg = UNBOX(MessageHeader, getThis());
1700 
1701   char *data = NULL;
1702   PHP_PROTO_SIZE data_len;
1703 
1704   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
1705       FAILURE) {
1706     return;
1707   }
1708 
1709   merge_from_string(data, data_len, desc, msg);
1710 }
1711 
PHP_METHOD(Message,serializeToJsonString)1712 PHP_METHOD(Message, serializeToJsonString) {
1713   Descriptor* desc =
1714       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
1715 
1716   zend_bool preserve_proto_fieldnames = false;
1717   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
1718                             &preserve_proto_fieldnames) == FAILURE) {
1719     return;
1720   }
1721 
1722   stringsink sink;
1723   stringsink_init(&sink);
1724 
1725   {
1726     const upb_handlers* serialize_handlers =
1727         msgdef_json_serialize_handlers(desc, preserve_proto_fieldnames);
1728     upb_json_printer* printer;
1729     stackenv se;
1730 
1731     stackenv_init(&se, "Error occurred during encoding: %s");
1732     printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
1733 
1734     putmsg(getThis(), desc, upb_json_printer_input(printer), 0, true TSRMLS_CC);
1735 
1736     PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
1737 
1738     stackenv_uninit(&se);
1739     stringsink_uninit(&sink);
1740   }
1741 }
1742 
PHP_METHOD(Message,mergeFromJsonString)1743 PHP_METHOD(Message, mergeFromJsonString) {
1744   Descriptor* desc =
1745       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
1746   MessageHeader* msg = UNBOX(MessageHeader, getThis());
1747 
1748   char *data = NULL;
1749   PHP_PROTO_SIZE data_len;
1750   zend_bool ignore_json_unknown = false;
1751 
1752   if (zend_parse_parameters(
1753           ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &data, &data_len,
1754           &ignore_json_unknown) ==
1755       FAILURE) {
1756     return;
1757   }
1758 
1759   // TODO(teboring): Check and respect string encoding. If not UTF-8, we need to
1760   // convert, because string handlers pass data directly to message string
1761   // fields.
1762 
1763   // TODO(teboring): Clear message.
1764 
1765   {
1766     const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
1767     stackenv se;
1768     upb_sink sink;
1769     upb_json_parser* parser;
1770     stackenv_init(&se, "Error occurred during parsing: %s");
1771 
1772     upb_sink_reset(&sink, get_fill_handlers(desc), msg);
1773     parser = upb_json_parser_create(se.arena, method, generated_pool->symtab,
1774                                     sink, &se.status, ignore_json_unknown);
1775     upb_bufsrc_putbuf(data, data_len, upb_json_parser_input(parser));
1776 
1777     stackenv_uninit(&se);
1778   }
1779 }
1780 
1781 // TODO(teboring): refactoring with putrawmsg
discard_unknown_fields(MessageHeader * msg)1782 static void discard_unknown_fields(MessageHeader* msg) {
1783   upb_msg_field_iter it;
1784 
1785   stringsink* unknown = DEREF(message_data(msg), 0, stringsink*);
1786   if (unknown != NULL) {
1787     stringsink_uninit(unknown);
1788     FREE(unknown);
1789     DEREF(message_data(msg), 0, stringsink*) = NULL;
1790   }
1791 
1792   // Recursively discard unknown fields of submessages.
1793   Descriptor* desc = msg->descriptor;
1794   TSRMLS_FETCH();
1795   for (upb_msg_field_begin(&it, desc->msgdef);
1796        !upb_msg_field_done(&it);
1797        upb_msg_field_next(&it)) {
1798     upb_fielddef* f = upb_msg_iter_field(&it);
1799     uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset;
1800     bool containing_oneof = false;
1801 
1802     if (upb_fielddef_containingoneof(f)) {
1803       uint32_t oneof_case_offset =
1804           desc->layout->fields[upb_fielddef_index(f)].case_offset;
1805       // For a oneof, check that this field is actually present -- skip all the
1806       // below if not.
1807       if (DEREF(message_data(msg), oneof_case_offset, uint32_t) !=
1808           upb_fielddef_number(f)) {
1809         continue;
1810       }
1811       // Otherwise, fall through to the appropriate singular-field handler
1812       // below.
1813       containing_oneof = true;
1814     }
1815 
1816     if (is_map_field(f)) {
1817       MapIter map_it;
1818       int len, size;
1819       const upb_fielddef* value_field;
1820 
1821       value_field = map_field_value(f);
1822       if (!upb_fielddef_issubmsg(value_field)) continue;
1823 
1824       zval* map_php = CACHED_PTR_TO_ZVAL_PTR(
1825           DEREF(message_data(msg), offset, CACHED_VALUE*));
1826       if (map_php == NULL) continue;
1827 
1828       Map* intern = UNBOX(Map, map_php);
1829       for (map_begin(map_php, &map_it TSRMLS_CC);
1830            !map_done(&map_it); map_next(&map_it)) {
1831         upb_value value = map_iter_value(&map_it, &len);
1832         const void* memory = raw_value(upb_value_memory(&value), value_field);
1833 #if PHP_MAJOR_VERSION < 7
1834         MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
1835 #else
1836         MessageHeader *submsg =
1837             (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
1838                 XtOffsetOf(MessageHeader, std));
1839 #endif
1840         discard_unknown_fields(submsg);
1841       }
1842     } else if (upb_fielddef_isseq(f)) {
1843       if (!upb_fielddef_issubmsg(f)) continue;
1844 
1845       zval* array_php = CACHED_PTR_TO_ZVAL_PTR(
1846           DEREF(message_data(msg), offset, CACHED_VALUE*));
1847       if (array_php == NULL) continue;
1848 
1849       int size, i;
1850       RepeatedField* intern = UNBOX(RepeatedField, array_php);
1851       HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
1852       size = zend_hash_num_elements(ht);
1853       if (size == 0) continue;
1854 
1855       for (i = 0; i < size; i++) {
1856         void* memory = repeated_field_index_native(intern, i TSRMLS_CC);
1857 #if PHP_MAJOR_VERSION < 7
1858         MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
1859 #else
1860         MessageHeader *submsg =
1861             (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
1862                 XtOffsetOf(MessageHeader, std));
1863 #endif
1864         discard_unknown_fields(submsg);
1865       }
1866     } else if (upb_fielddef_issubmsg(f)) {
1867       zval* submsg_php = CACHED_PTR_TO_ZVAL_PTR(
1868           DEREF(message_data(msg), offset, CACHED_VALUE*));
1869       if (Z_TYPE_P(submsg_php) == IS_NULL) continue;
1870       MessageHeader* submsg = UNBOX(MessageHeader, submsg_php);
1871       discard_unknown_fields(submsg);
1872     }
1873   }
1874 }
1875 
PHP_METHOD(Message,discardUnknownFields)1876 PHP_METHOD(Message, discardUnknownFields) {
1877   MessageHeader* msg = UNBOX(MessageHeader, getThis());
1878   discard_unknown_fields(msg);
1879 }
1880