Init basesystem source codes.
[staging/basesystem.git] / otherservice / rpc_library / library / src / rpc_marshall.c
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file rpc_marshall.c
19  * @brief RPC Library Internal Implementation--Argument Conversion During API Calls
20  *
21  */
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <netinet/in.h>
28 #include <math.h>
29
30 #include <other_service/rpc.h>
31 #include "rpc_internal.h"
32
33 #include "apidef.tab.h"
34 #include "apidef.h"
35
36 /** @addtogroup RPClib_in
37  * @{
38  */
39 /** Structures for String Add Operations */
40 typedef struct {
41   char *start;
42   char *wp;
43   unsigned int units;
44   unsigned int remain;
45 } RpcString;
46
47 #ifdef STRETCH_STRING
48 #define _STRING_ALLOC_UNIT 512
49 #else
50 /*
51  * Batch allocate total bytes of arguments + data to be added internally 
52  * (maximal 6 bytes per argument)
53  */
54 #define _STRING_ALLOC_UNIT \
55   (RPC_MAX_API_ARG_TOTAL_SIZE + RPC_MAX_API_ARG_NUM * (2 + 4))
56 #endif
57
58 #define _ENOUGH_SPACE_FOR_ALL_TYPES \
59   (sizeof(UINT64) > sizeof(double) ? sizeof(UINT64) : sizeof(double))
60
61 static RpcString* NewRpcString(void);
62 #ifdef STRETCH_STRING
63 static int StretchString(RpcString *str, UINT16 bytes);
64 #endif
65 static char *CopyString(RpcString *str, unsigned int *size);
66 static void DestroyString(RpcString *str);
67 static inline int AppendString(RpcString *str,
68        const UINT8 *append, UINT16 applen);
69 static inline int MarshallUINT8(RpcString *str, UINT8 uc);
70 static inline int MarshallUINT16(RpcString *str, UINT16 uh);
71 static inline int MarshallUINT32(RpcString *str, UINT32 ui);
72 static inline int MarshallUINT64(RpcString *str, UINT64 ul);
73 static inline int Marshallfloat(RpcString *str, float f);
74 static inline int Marshalldouble(RpcString *str, double d);
75 static inline int MarshallUINT8Stream(RpcString *str, const UINT8 *buf,
76           UINT16 bytes);
77 static inline int MarshallString(RpcString *str, char *buf,
78           UINT16 bytes);
79 static inline int MarshallNullPointer(RpcString *str);
80 static inline int MarshallPointer(RpcString *str);
81
82 static RpcString *
83 NewRpcString(void) {
84   RpcString *str;
85
86   str = rpc_malloc(sizeof(RpcString));
87   if (str == NULL) {  // LCOV_EXCL_START 5: fail safe for libc malloc
88     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
89     return NULL;
90   }  // LCOV_EXCL_STOP
91
92   str->start = rpc_malloc(_STRING_ALLOC_UNIT);
93   if (str->start == NULL) {  // LCOV_EXCL_START 5: fail safe for libc malloc
94     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
95     rpc_free(str);
96     return NULL;
97   }  // LCOV_EXCL_STOP
98   str->start[0] = '\0';
99   str->wp = str->start;
100   str->units = 1;
101   str->remain = _STRING_ALLOC_UNIT - 1;
102
103   return str;
104 }
105
106 #ifdef STRETCH_STRING
107 static int
108 StretchString(RpcString *str, UINT16 bytes) {
109   unsigned int oldunits = str->units;
110   unsigned int units = 1 + (bytes / _STRING_ALLOC_UNIT) + oldunits;
111   if (units == oldunits) {
112     return 0;
113   }
114   unsigned int length = str->wp - str->start;
115   char *newp = rpc_malloc(units * _STRING_ALLOC_UNIT);
116   if (newp == NULL) {
117     return -1;
118   }
119   memcpy(newp, str->start, length);
120   rpc_free(str->start);
121   str->start = newp;
122   str->wp = str->start + length;
123   *(str->wp) = '\0';
124   str->units = units;
125   str->remain += (units - oldunits) * _STRING_ALLOC_UNIT;
126   return 0;
127 }
128 #endif  /* STRETCH_STRING */
129
130 static inline int
131 AppendString(RpcString *str, const UINT8 *append, UINT16 applen) {
132   rpc_assert(append != NULL);  // LCOV_EXCL_BR_LINE 6: double check
133 #ifdef STRETCH_STRING
134   if (applen > str->remain) {
135     if (StretchString(str, applen - str->remain) < 0) {
136       return -1;
137     }
138   }
139 #else
140   rpc_assert(applen <= str->remain);  // LCOV_EXCL_BR_LINE 6: double check
141 #endif
142   memcpy(str->wp, append, applen);
143   str->wp += applen;
144   str->remain -= applen;
145   return 0;
146 }
147
148 static char *
149 CopyString(RpcString *str, unsigned int *size) {
150   unsigned int length = (unsigned int)(str->wp - str->start);
151   char *ret = rpc_malloc(length);
152   // LCOV_EXCL_BR_START 5: fail safe for libc malloc
153   if (ret == NULL) {
154     return NULL;
155   }
156   // LCOV_EXCL_BR_STOP
157   memcpy(ret, str->start, length);
158   if (size != NULL) {
159     *size = length;
160   }
161
162   return ret;
163 }
164
165 static void
166 DestroyString(RpcString *str) {
167   rpc_free(str->start);
168   rpc_free(str);
169 }
170
171 static inline int
172 MarshallUINT8(RpcString *str, UINT8 c) {
173   UINT8 buf[1 + sizeof(c)];
174   buf[0] = 'C';
175   buf[1] = c;
176   return AppendString(str, buf, sizeof(buf));
177 }
178
179 static inline int
180 MarshallUINT8Stream(RpcString *str, const UINT8 *buf, UINT16 bytes) {
181   int ret = AppendString(str, (const UINT8 *)"B", 1);
182   if (ret < 0) {  // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
183     return -1;
184   }
185   return AppendString(str, buf, bytes);
186 }
187
188 static inline int
189 MarshallVararrayStream(RpcString *str, const UINT8 *buf, UINT16 bytes) {
190   char head_str[1+4+1+1];  /* Area where symbol "V" + size is stored */
191   sprintf(head_str, "V%03d ", bytes);
192   head_str[1+4+1] = '\0';
193
194   if (AppendString(str, (const UINT8 *)head_str, (UINT16)strlen(head_str)) < 0) {  // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
195     return -1;
196   }
197
198   if (AppendString(str, buf, bytes) < 0) {  // LCOV_EXCL_BR_LINE 15: inline func rpc_marshall.c
199     return -1;
200   }
201   return 0;
202 }
203
204 static inline int
205 MarshallString(RpcString *str, char *buf, UINT16 bytes) {
206   char *p = buf;
207   UINT16 count = 0;
208   /* count the number of bytes in the argument */
209   while(*p != '\0' && count < (UINT16)(bytes - 1)) {
210     count++;
211     p++;
212   }
213
214   char count_str[1+strlen("1024")+1+1];
215   sprintf(count_str, "S%d ", count);
216
217   if (AppendString(str, (const UINT8 *)count_str, (UINT16)strlen(count_str)) < 0 || AppendString(str, (const UINT8 *)buf, count) < 0) {  // LCOV_EXCL_BR_LINE 11: Unexpected branch // NOLINT(readability/nolint)
218     return -1;
219   }
220   return 0;
221 }
222
223 static int
224 MarshallUINT16(RpcString *str, UINT16 uh) {
225   UINT8 buf[1 + sizeof(uh)];
226   buf[0] = 'H';
227   memcpy(buf + 1, &uh, sizeof(uh));
228   return AppendString(str, buf, sizeof(buf));
229 }
230
231 static inline int
232 MarshallUINT32(RpcString *str, UINT32 ui) {
233   UINT8 buf[1 + sizeof(ui)];
234   buf[0] = 'I';
235   memcpy(buf + 1, &ui, sizeof(ui));
236   return AppendString(str, buf, sizeof(buf));
237 }
238
239 static inline int
240 Marshallint(RpcString *str, int i) {
241   return MarshallUINT32(str, (UINT32)i);
242 }
243
244 static inline int
245 MarshallUINT64(RpcString *str, UINT64 ul) {
246   UINT8 buf[1 + sizeof(ul)];
247   buf[0] = 'L';
248   memcpy(buf + 1, &ul, sizeof(ul));
249   return AppendString(str, buf, sizeof(buf));
250 }
251
252 static inline int
253 Marshallfloat(RpcString *str, float f) {
254   UINT8 buf[1 + sizeof(f)];
255   buf[0] = 'F';
256   memcpy(buf + 1, &f, sizeof(f));
257   return AppendString(str, buf, sizeof(buf));
258 }
259
260 static inline int
261 Marshalldouble(RpcString *str, double d) {
262   UINT8 buf[1 + sizeof(d)];
263   buf[0] = 'D';
264   memcpy(buf + 1, &d, sizeof(d));
265   return AppendString(str, buf, sizeof(buf));
266 }
267
268 static inline int
269 MarshallPointer(RpcString *str) {
270   /* only to specify that a non-NULL pointer was delivered */
271   return AppendString(str, (const UINT8 *)"P", 1);
272 }
273
274 static inline int
275 MarshallNullPointer(RpcString *str  /*, int code*/) {
276   return AppendString(str, (const UINT8 *)"N", 1);
277 }
278
279 /** @ingroup RPClib_in
280  */
281
282 #define MACROMarshallPointer(TYPE) \
283   do { \
284     TYPE *p = (TYPE *)temp; \
285     error = Marshall##TYPE(str, *p); \
286   } while(0)
287
288 #define MACROMarshallValue(TYPE, STACK_TYPE) \
289   do { \
290     TYPE value = (TYPE)va_arg(ap, STACK_TYPE); \
291     error = Marshall##TYPE(str, value); \
292   } while(0)
293
294 char *
295 RPC_marshall_arguments(unsigned int *size, int dont_marshall_out_pointer,
296                        int num_args, ...) {
297   rpc_assert(num_args <= RPC_MAX_API_ARG_NUM);  // LCOV_EXCL_BR_LINE 6: double check
298   va_list ap;
299
300   RpcString *str;
301   str = NewRpcString();
302   if (str == NULL) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc malloc
303     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
304     return NULL;  // LCOV_EXCL_LINE 5: fail safe for libc malloc
305   }
306
307   va_start(ap, num_args);
308
309   int ii, error;
310   error = 0;
311
312   for(ii = 0 ; ii < num_args && error == 0 ; ii++) {
313     unsigned int code, is_vararray, is_pointer, in_out, out_only;
314     UINT16 bytes;
315     unsigned int val = va_arg(ap, unsigned int);
316
317     RPC_marshall_flag flag;
318     flag.all = ntohl(val);
319     code = flag.bits.code;
320     is_vararray = flag.bits.is_vararray;
321     is_pointer = flag.bits.is_pointer;
322     in_out = flag.bits.in_out;
323     bytes = flag.bits.bytes;
324     rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE);  // LCOV_EXCL_BR_LINE 6: double check
325
326
327     out_only = 0;
328     if (in_out == RPC_OUT_ARG) {  /* OUT only argument */
329       out_only = 1;
330     }
331
332     if (is_pointer) {  /* Argument passed by pointer */
333
334       void *temp = (void *)va_arg(ap, void *);
335       if (temp == NULL) {
336         /* NULL pointer */
337         error = MarshallNullPointer(str);
338       } else if (dont_marshall_out_pointer && out_only) {
339         /* Not refer to the contents of a pointer */
340         error = MarshallPointer(str);
341       } else {/* Marshall the contents of pointers */
342         if (is_vararray) {
343           /* Variable-length array */
344           error = MarshallVararrayStream(str, temp, bytes);
345         } else {
346           switch(code) {
347             case rpc_CHAR:
348             case rpc_INT8:
349             case rpc_UINT8:
350               MACROMarshallPointer(UINT8);
351               break;
352             case rpc_INT16:
353             case rpc_UINT16:
354               MACROMarshallPointer(UINT16);
355               break;
356             case rpc_INT:
357             case rpc_SINT:
358             case rpc_UINT:
359               MACROMarshallPointer(int);
360               break;
361             case rpc_INT32:
362             case rpc_UINT32:
363               MACROMarshallPointer(UINT32);
364               break;
365             case rpc_INT64:
366             case rpc_UINT64:
367               MACROMarshallPointer(UINT64);
368               break;
369             case rpc_FLOAT:
370               MACROMarshallPointer(float);
371               break;
372             case rpc_DOUBLE:
373               MACROMarshallPointer(double);
374               break;
375             case rpc_STRING:
376               error = MarshallString(str, temp, bytes);
377               break;
378             case rpc_USER_DEFINED:
379               error = MarshallUINT8Stream(str, temp, bytes);
380               break;
381             default:
382               error = -1;
383               break;
384           }
385         }
386       }
387     } else {/* Argument passed by value */
388
389       /* Note: In this area, the code depends on the CPU architecture */
390
391       switch(code) {
392         case rpc_CHAR:
393         case rpc_INT8:
394         case rpc_UINT8:
395           MACROMarshallValue(UINT8, unsigned int);
396           break;
397         case rpc_INT16:
398         case rpc_UINT16:
399           MACROMarshallValue(UINT16, unsigned int);
400           break;
401         case rpc_INT:
402         case rpc_SINT:
403         case rpc_UINT:
404           MACROMarshallValue(int, int);  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
405           break;
406         case rpc_INT32:
407         case rpc_UINT32:
408           MACROMarshallValue(UINT32, UINT32);  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
409           break;
410         case rpc_INT64:
411         case rpc_UINT64:
412           MACROMarshallValue(UINT64, UINT64);  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
413           break;
414         case rpc_FLOAT:
415           MACROMarshallValue(float, double);  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
416           break;
417         case rpc_DOUBLE:
418           MACROMarshallValue(double, double);  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
419           break;
420         case rpc_USER_DEFINED:
421           rpc_assert(bytes <= sizeof(UINT64));
422           /* This area is very architecture-dependent! */
423           if (bytes <= sizeof(UINT32)) {
424             UINT32 value = (UINT32)va_arg(ap, UINT32);  // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h
425             error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes);
426           } else if (bytes <= sizeof(UINT64)) {  // LCOV_EXCL_BR_LINE 6: double check
427             UINT64 value = (UINT64)va_arg(ap, UINT64);  // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h
428             error = MarshallUINT8Stream(str, (UINT8 *)&value, bytes);
429           }
430           break;
431         default:
432           error = -1;
433           break;
434       }
435     }
436   }
437   va_end(ap);
438
439   if (error != 0) {
440     DestroyString(str);
441     return NULL;
442   }
443
444   char *ret = CopyString(str, size);
445   DestroyString(str);
446   return ret;
447 }
448
449 static inline int DeMarshallUINT8(const char *from, UINT8 *ucp);
450 static inline int DeMarshallUINT16(const char *from, UINT16 *uhp);
451 static inline int DeMarshallUINT32(const char *from, UINT32 *uip);
452 static inline int DeMarshallUINT64(const char *from, UINT64 *ulp);
453 static inline int DeMarshallfloat(const char *from, float *fp);
454 static inline int DeMarshalldouble(const char *from, double *dp);
455 static inline int DeMarshallUINT8Stream(const char *from, UINT8 *buffer,
456             UINT16 bytes);
457 static inline int DeMarshallString(const char *from, char *buffer,
458            UINT16 bytes);
459
460 static inline int
461 DeMarshallUINT8(const char *from, UINT8 *ucp) {
462   if (*from == 'C') {
463     *ucp = *(UINT8 *)(from + 1);
464     return 1 + sizeof(*ucp);
465   } else {
466     return -1;
467   }
468 }
469
470 static inline int
471 DeMarshallUINT16(const char *from, UINT16 *uhp) {
472   if (*from == 'H') {
473     memcpy(uhp, from + 1, sizeof(*uhp));
474     return 1 + sizeof(*uhp);
475   } else {
476     return -1;
477   }
478 }
479
480 static inline int
481 DeMarshallUINT32(const char *from, UINT32 *uip) {
482   if (*from == 'I') {
483     memcpy(uip, from + 1, sizeof(*uip));
484     return 1 + sizeof(*uip);
485   } else {
486     return -1;
487   }
488 }
489
490 static inline int
491 DeMarshallint(const char *from, int *ip) {
492   return DeMarshallUINT32(from, (UINT32 *)ip);
493 }
494
495 static inline int
496 DeMarshallUINT64(const char *from, UINT64 *ulp) {
497   if (*from == 'L') {
498     memcpy(ulp, from + 1, sizeof(*ulp));
499     return 1 + sizeof(*ulp);
500   } else {
501     return -1;
502   }
503 }
504
505 static inline int
506 DeMarshallfloat(const char *from, float *fp) {
507   if (*from == 'F') {
508     memcpy(fp, from + 1, sizeof(*fp));
509     return 1 + sizeof(*fp);
510   } else {
511     return -1;
512   }
513 }
514
515 static inline int
516 DeMarshalldouble(const char *from, double *dp) {
517   if (*from == 'D') {
518     memcpy(dp, from + 1, sizeof(*dp));
519
520     return 1 + sizeof(*dp);
521   } else {
522     return -1;
523   }
524 }
525
526 static inline int
527 DeMarshallUINT8Stream(const char *from, UINT8 *buffer, UINT16 bytes) {
528   if (*from == 'B') {
529     memcpy(buffer, from + 1, bytes);
530     return (int)(1 + bytes);
531   } else {
532     return -1;
533   }
534 }
535
536 static inline int
537 DeMarshallString(const char *from, char *buffer, UINT16 bytes) {
538   if (*from == 'S') {
539     char *start;
540     long len = strtol(from + 1, &start, 10);
541     if (len < 0 || len >= bytes) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol
542       return -1;
543     }
544     start++;  /* skip ' ' */
545     int skip = (int)(start - from);
546     memcpy(buffer, start, (size_t)len);
547     buffer[len] = '\0';
548     return skip + (int)len;
549   } else {
550     return -1;
551   }
552 }
553
554 /* Variable-length array data */
555 static inline int
556 DemarshallVararrayInfo(const char *from, UINT16 *bytes/* OUT */) {
557   if (*from == 'V') {
558     char *end;
559     long len = strtol((char *)(from + 1), &end, 10);
560     if (len <= 0 || len > RPC_MAX_API_ARG_SIZE) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc strtol
561       return -1;
562     }
563     *bytes = (UINT16)len;
564     return (int)(end - from + 1);  /* skip ' ' */
565   } else {
566     return -1;
567   }
568 }
569
570 /** @ingroup RPClib_in
571  */
572
573 #define MACRODemarshall(TYPE) \
574     do {\
575   TYPE *p; \
576   if (need_alloc && is_pointer) { \
577     p = rpc_malloc(sizeof(TYPE)); \
578     *(TYPE **)temp = p; \
579   } else { \
580     p = (TYPE *)temp; \
581   } \
582   if (p != NULL) { \
583     ret = DeMarshall##TYPE(from, p); \
584   } \
585     } while(0)
586
587 int
588 RPC_demarshall_arguments(const char *from, unsigned int size,
589        int need_alloc, int num_args, ...) {
590   rpc_assert(num_args <= RPC_MAX_API_ARG_NUM);  // LCOV_EXCL_BR_LINE 6: double check
591   va_list ap;
592   va_start(ap, num_args);
593
594   int ii, error;
595   error = 0;
596   int remain_len = (int)size;
597
598   for(ii = 0 ; ii < num_args && error == 0 && remain_len > 0 ; ii++) {
599     unsigned int code, is_pointer, is_vararray;
600     UINT16 bytes;
601     unsigned int val = va_arg(ap, unsigned int);
602     RPC_marshall_flag flag;
603     flag.all = ntohl(val);
604     code = flag.bits.code;
605     is_vararray = flag.bits.is_vararray;
606     is_pointer = flag.bits.is_pointer;
607     bytes = flag.bits.bytes;
608     rpc_assert(bytes <= RPC_MAX_API_ARG_SIZE);  // LCOV_EXCL_BR_LINE 6: double check
609
610
611     void *temp = va_arg(ap, void *);
612     int ret = -1;
613
614     if (*from == 'N') {  /* NULL pointer */
615       if (bytes > 0 || is_pointer != 0) {
616         if (need_alloc) {
617           *(void **)temp = NULL;
618         } else {
619           /* do nothing */
620         }
621         ret = 1;
622       }
623     } else if (*from == 'P') {  /* Pointer(no content) */
624       if (need_alloc) {
625         if (bytes > 0) {  /* String type or user-defined type */
626           *(void **)temp = rpc_malloc(bytes);
627         } else if (is_pointer != 0) {  /* Other pointers */
628           *(void **)temp = rpc_malloc(_ENOUGH_SPACE_FOR_ALL_TYPES);
629         }
630         ret = 1;
631       }
632     } else {  /* non-NULL pointer */
633       if ( is_vararray ) {  /* Variable-length array */
634         ret = DemarshallVararrayInfo(from, &bytes);
635         if( ret < 0 ) {
636           va_end(ap);
637           return -1;  /* pgr0524 */
638         }
639       char *p;
640       if (need_alloc) {
641         p = rpc_malloc(sizeof(char)*bytes);
642         *(char **)temp = p;
643       } else {
644         p = (char *)temp;  /* pgr0524 */
645       }
646       if (p != NULL) {
647         memcpy(p, from + ret, bytes);
648         ret += bytes;
649       }
650       } else {
651         switch(code) {
652           case rpc_CHAR:
653           case rpc_INT8:
654           case rpc_UINT8:
655             MACRODemarshall(UINT8);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
656             break;
657           case rpc_INT16:
658           case rpc_UINT16:
659             MACRODemarshall(UINT16);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
660             break;
661           case rpc_INT:
662           case rpc_SINT:
663           case rpc_UINT:
664             MACRODemarshall(int);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
665             break;
666           case rpc_INT32:
667           case rpc_UINT32:
668             MACRODemarshall(UINT32);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
669             break;
670           case rpc_INT64:
671           case rpc_UINT64:
672             MACRODemarshall(UINT64);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
673             break;
674           case rpc_FLOAT:
675             MACRODemarshall(float);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
676             break;
677           case rpc_DOUBLE:
678             MACRODemarshall(double);  /* pgr0524 */  // LCOV_EXCL_BR_LINE 15: marco defined in rpc_marshall.c
679             break;
680           case rpc_USER_DEFINED: {
681             UINT8 *p;
682             if (need_alloc && is_pointer) {
683               p = rpc_malloc(bytes);
684               *(UINT8 **)temp = p;
685             } else {
686               p = (UINT8 *)temp;  /* pgr0524 */
687             }
688             if (p != NULL) {
689               ret = DeMarshallUINT8Stream(from, p, bytes);
690             }
691             break;
692           }
693           case rpc_STRING: {
694             char *p;
695             if (need_alloc) {
696               p = rpc_malloc(sizeof(char)*bytes);
697               *(char **)temp = p;
698             } else {
699               p = (char *)temp;  /* pgr0524 */
700             }
701             if (p != NULL) {
702               ret = DeMarshallString(from, p, bytes);
703             }
704             break;
705           }
706           default:
707             break;
708         }
709       }
710     }
711     if (ret < 0) {
712       error = 1;
713     } else {
714       remain_len -= ret;
715       from += ret;
716     }
717   }
718   va_end(ap);
719
720   if (error) {
721     return -1;  /* pgr0524 */
722   } else {
723     return 0;  /* pgr0524 */
724   }
725 }
726
727 void
728 RPC_marshall_free(int num, ...) {
729   va_list ap;
730   va_start(ap, num);
731
732   int i;
733   for(i = 0 ; i < num ; i++) {
734     void *ptr = va_arg(ap, void *);  // LCOV_EXCL_BR_LINE 15: macro defined in stdarg.h
735     if (ptr != NULL) {
736       rpc_free(ptr);
737     }
738   }
739   va_end(ap);
740 }