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