manual: Clarify undefined behavior of feenableexcept (BZ 31019)
[glibc.git] / sunrpc / xdr.c
bloba76094d6dab550e116eed407f679c17bf9992e74
1 /*
2 * xdr.c, Generic XDR routines implementation.
4 * Copyright (c) 2010, Oracle America, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * These are the "generic" xdr routines used to serialize and de-serialize
34 * most common data items. See xdr.h for more info on the interface to
35 * xdr.
38 #include <stdio.h>
39 #include <limits.h>
40 #include <string.h>
41 #include <libintl.h>
42 #include <wchar.h>
43 #include <stdint.h>
45 #include <rpc/types.h>
46 #include <rpc/xdr.h>
47 #include <shlib-compat.h>
51 * constants specific to the xdr "protocol"
53 #define XDR_FALSE ((long) 0)
54 #define XDR_TRUE ((long) 1)
55 #define LASTUNSIGNED ((u_int) 0-1)
58 * for unit alignment
60 static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
63 * Free a data structure using XDR
64 * Not a filter, but a convenient utility nonetheless
66 void
67 xdr_free (xdrproc_t proc, char *objp)
69 XDR x;
71 x.x_op = XDR_FREE;
72 (*proc) (&x, objp);
74 #ifdef EXPORT_RPC_SYMBOLS
75 libc_hidden_def (xdr_free)
76 #else
77 libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0)
78 #endif
81 * XDR nothing
83 bool_t
84 xdr_void (void)
86 return TRUE;
88 #ifdef EXPORT_RPC_SYMBOLS
89 libc_hidden_def (xdr_void)
90 #else
91 libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0)
92 #endif
95 * XDR integers
97 bool_t
98 xdr_int (XDR *xdrs, int *ip)
101 #if INT_MAX < LONG_MAX
102 long l;
104 switch (xdrs->x_op)
106 case XDR_ENCODE:
107 l = (long) *ip;
108 return XDR_PUTLONG (xdrs, &l);
110 case XDR_DECODE:
111 if (!XDR_GETLONG (xdrs, &l))
113 return FALSE;
115 *ip = (int) l;
116 /* Fall through. */
117 case XDR_FREE:
118 return TRUE;
120 return FALSE;
121 #elif INT_MAX == LONG_MAX
122 return xdr_long (xdrs, (long *) ip);
123 #elif INT_MAX == SHRT_MAX
124 return xdr_short (xdrs, (short *) ip);
125 #else
126 #error unexpected integer sizes in_xdr_int()
127 #endif
129 #ifdef EXPORT_RPC_SYMBOLS
130 libc_hidden_def (xdr_int)
131 #else
132 libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0)
133 #endif
136 * XDR unsigned integers
138 bool_t
139 xdr_u_int (XDR *xdrs, u_int *up)
141 #if UINT_MAX < ULONG_MAX
142 long l;
144 switch (xdrs->x_op)
146 case XDR_ENCODE:
147 l = (u_long) * up;
148 return XDR_PUTLONG (xdrs, &l);
150 case XDR_DECODE:
151 if (!XDR_GETLONG (xdrs, &l))
153 return FALSE;
155 *up = (u_int) (u_long) l;
156 /* Fall through. */
157 case XDR_FREE:
158 return TRUE;
160 return FALSE;
161 #elif UINT_MAX == ULONG_MAX
162 return xdr_u_long (xdrs, (u_long *) up);
163 #elif UINT_MAX == USHRT_MAX
164 return xdr_short (xdrs, (short *) up);
165 #else
166 #error unexpected integer sizes in_xdr_u_int()
167 #endif
169 #ifdef EXPORT_RPC_SYMBOLS
170 libc_hidden_def (xdr_u_int)
171 #else
172 libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0)
173 #endif
176 * XDR long integers
177 * The definition of xdr_long() is kept for backward
178 * compatibility. Instead xdr_int() should be used.
180 bool_t
181 xdr_long (XDR *xdrs, long *lp)
184 if (xdrs->x_op == XDR_ENCODE
185 && (sizeof (int32_t) == sizeof (long)
186 || (int32_t) *lp == *lp))
187 return XDR_PUTLONG (xdrs, lp);
189 if (xdrs->x_op == XDR_DECODE)
190 return XDR_GETLONG (xdrs, lp);
192 if (xdrs->x_op == XDR_FREE)
193 return TRUE;
195 return FALSE;
197 #ifdef EXPORT_RPC_SYMBOLS
198 libc_hidden_def (xdr_long)
199 #else
200 libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0)
201 #endif
204 * XDR unsigned long integers
205 * The definition of xdr_u_long() is kept for backward
206 * compatibility. Instead xdr_u_int() should be used.
208 bool_t
209 xdr_u_long (XDR *xdrs, u_long *ulp)
211 switch (xdrs->x_op)
213 case XDR_DECODE:
215 long int tmp;
217 if (XDR_GETLONG (xdrs, &tmp) == FALSE)
218 return FALSE;
220 *ulp = (uint32_t) tmp;
221 return TRUE;
224 case XDR_ENCODE:
225 if (sizeof (uint32_t) != sizeof (u_long)
226 && (uint32_t) *ulp != *ulp)
227 return FALSE;
229 return XDR_PUTLONG (xdrs, (long *) ulp);
231 case XDR_FREE:
232 return TRUE;
234 return FALSE;
236 #ifdef EXPORT_RPC_SYMBOLS
237 libc_hidden_def (xdr_u_long)
238 #else
239 libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0)
240 #endif
243 * XDR hyper integers
244 * same as xdr_u_hyper - open coded to save a proc call!
246 bool_t
247 xdr_hyper (XDR *xdrs, quad_t *llp)
249 long int t1, t2;
251 if (xdrs->x_op == XDR_ENCODE)
253 t1 = (long) ((*llp) >> 32);
254 t2 = (long) (*llp);
255 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
258 if (xdrs->x_op == XDR_DECODE)
260 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
261 return FALSE;
262 *llp = ((quad_t) t1) << 32;
263 *llp |= (uint32_t) t2;
264 return TRUE;
267 if (xdrs->x_op == XDR_FREE)
268 return TRUE;
270 return FALSE;
272 #ifdef EXPORT_RPC_SYMBOLS
273 libc_hidden_def (xdr_hyper)
274 #else
275 libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1)
276 #endif
279 * XDR hyper integers
280 * same as xdr_hyper - open coded to save a proc call!
282 bool_t
283 xdr_u_hyper (XDR *xdrs, u_quad_t *ullp)
285 long int t1, t2;
287 if (xdrs->x_op == XDR_ENCODE)
289 t1 = (unsigned long) ((*ullp) >> 32);
290 t2 = (unsigned long) (*ullp);
291 return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2));
294 if (xdrs->x_op == XDR_DECODE)
296 if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
297 return FALSE;
298 *ullp = ((u_quad_t) t1) << 32;
299 *ullp |= (uint32_t) t2;
300 return TRUE;
303 if (xdrs->x_op == XDR_FREE)
304 return TRUE;
306 return FALSE;
308 #ifdef EXPORT_RPC_SYMBOLS
309 libc_hidden_def (xdr_u_hyper)
310 #else
311 libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1)
312 #endif
314 bool_t
315 xdr_longlong_t (XDR *xdrs, quad_t *llp)
317 return xdr_hyper (xdrs, llp);
319 #ifdef EXPORT_RPC_SYMBOLS
320 libc_hidden_def (xdr_longlong_t)
321 #else
322 libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1)
323 #endif
325 bool_t
326 xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp)
328 return xdr_u_hyper (xdrs, ullp);
330 #ifdef EXPORT_RPC_SYMBOLS
331 libc_hidden_def (xdr_u_longlong_t)
332 #else
333 libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1)
334 #endif
337 * XDR short integers
339 bool_t
340 xdr_short (XDR *xdrs, short *sp)
342 long l;
344 switch (xdrs->x_op)
346 case XDR_ENCODE:
347 l = (long) *sp;
348 return XDR_PUTLONG (xdrs, &l);
350 case XDR_DECODE:
351 if (!XDR_GETLONG (xdrs, &l))
353 return FALSE;
355 *sp = (short) l;
356 return TRUE;
358 case XDR_FREE:
359 return TRUE;
361 return FALSE;
363 #ifdef EXPORT_RPC_SYMBOLS
364 libc_hidden_def (xdr_short)
365 #else
366 libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0)
367 #endif
370 * XDR unsigned short integers
372 bool_t
373 xdr_u_short (XDR *xdrs, u_short *usp)
375 long l;
377 switch (xdrs->x_op)
379 case XDR_ENCODE:
380 l = (u_long) * usp;
381 return XDR_PUTLONG (xdrs, &l);
383 case XDR_DECODE:
384 if (!XDR_GETLONG (xdrs, &l))
386 return FALSE;
388 *usp = (u_short) (u_long) l;
389 return TRUE;
391 case XDR_FREE:
392 return TRUE;
394 return FALSE;
396 #ifdef EXPORT_RPC_SYMBOLS
397 libc_hidden_def (xdr_u_short)
398 #else
399 libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0)
400 #endif
404 * XDR a char
406 bool_t
407 xdr_char (XDR *xdrs, char *cp)
409 int i;
411 i = (*cp);
412 if (!xdr_int (xdrs, &i))
414 return FALSE;
416 *cp = i;
417 return TRUE;
419 #ifdef EXPORT_RPC_SYMBOLS
420 libc_hidden_def (xdr_char)
421 #else
422 libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0)
423 #endif
426 * XDR an unsigned char
428 bool_t
429 xdr_u_char (XDR *xdrs, u_char *cp)
431 u_int u;
433 u = (*cp);
434 if (!xdr_u_int (xdrs, &u))
436 return FALSE;
438 *cp = u;
439 return TRUE;
441 #ifdef EXPORT_RPC_SYMBOLS
442 libc_hidden_def (xdr_u_char)
443 #else
444 libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0)
445 #endif
448 * XDR booleans
450 bool_t
451 xdr_bool (XDR *xdrs, bool_t *bp)
453 long lb;
455 switch (xdrs->x_op)
457 case XDR_ENCODE:
458 lb = *bp ? XDR_TRUE : XDR_FALSE;
459 return XDR_PUTLONG (xdrs, &lb);
461 case XDR_DECODE:
462 if (!XDR_GETLONG (xdrs, &lb))
464 return FALSE;
466 *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
467 return TRUE;
469 case XDR_FREE:
470 return TRUE;
472 return FALSE;
474 #ifdef EXPORT_RPC_SYMBOLS
475 libc_hidden_def (xdr_bool)
476 #else
477 libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0)
478 #endif
481 * XDR enumerations
483 bool_t
484 xdr_enum (XDR *xdrs, enum_t *ep)
486 enum sizecheck
488 SIZEVAL
489 }; /* used to find the size of an enum */
492 * enums are treated as ints
494 if (sizeof (enum sizecheck) == 4)
496 #if INT_MAX < LONG_MAX
497 long l;
499 switch (xdrs->x_op)
501 case XDR_ENCODE:
502 l = *ep;
503 return XDR_PUTLONG (xdrs, &l);
505 case XDR_DECODE:
506 if (!XDR_GETLONG (xdrs, &l))
508 return FALSE;
510 *ep = l;
511 /* Fall through. */
512 case XDR_FREE:
513 return TRUE;
516 return FALSE;
517 #else
518 return xdr_long (xdrs, (long *) ep);
519 #endif
521 else if (sizeof (enum sizecheck) == sizeof (short))
523 return xdr_short (xdrs, (short *) ep);
525 else
527 return FALSE;
530 #ifdef EXPORT_RPC_SYMBOLS
531 libc_hidden_def (xdr_enum)
532 #else
533 libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0)
534 #endif
537 * XDR opaque data
538 * Allows the specification of a fixed size sequence of opaque bytes.
539 * cp points to the opaque object and cnt gives the byte length.
541 bool_t
542 xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt)
544 u_int rndup;
545 static char crud[BYTES_PER_XDR_UNIT];
548 * if no data we are done
550 if (cnt == 0)
551 return TRUE;
554 * round byte count to full xdr units
556 rndup = cnt % BYTES_PER_XDR_UNIT;
557 if (rndup > 0)
558 rndup = BYTES_PER_XDR_UNIT - rndup;
560 switch (xdrs->x_op)
562 case XDR_DECODE:
563 if (!XDR_GETBYTES (xdrs, cp, cnt))
565 return FALSE;
567 if (rndup == 0)
568 return TRUE;
569 return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup);
571 case XDR_ENCODE:
572 if (!XDR_PUTBYTES (xdrs, cp, cnt))
574 return FALSE;
576 if (rndup == 0)
577 return TRUE;
578 return XDR_PUTBYTES (xdrs, xdr_zero, rndup);
580 case XDR_FREE:
581 return TRUE;
583 return FALSE;
585 #ifdef EXPORT_RPC_SYMBOLS
586 libc_hidden_def (xdr_opaque)
587 #else
588 libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0)
589 #endif
592 * XDR counted bytes
593 * *cpp is a pointer to the bytes, *sizep is the count.
594 * If *cpp is NULL maxsize bytes are allocated
596 bool_t
597 xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
599 char *sp = *cpp; /* sp is the actual string pointer */
600 u_int nodesize;
603 * first deal with the length since xdr bytes are counted
605 if (!xdr_u_int (xdrs, sizep))
607 return FALSE;
609 nodesize = *sizep;
610 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE))
612 return FALSE;
616 * now deal with the actual bytes
618 switch (xdrs->x_op)
620 case XDR_DECODE:
621 if (nodesize == 0)
623 return TRUE;
625 if (sp == NULL)
627 *cpp = sp = (char *) mem_alloc (nodesize);
629 if (sp == NULL)
631 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
632 return FALSE;
634 /* Fall through. */
636 case XDR_ENCODE:
637 return xdr_opaque (xdrs, sp, nodesize);
639 case XDR_FREE:
640 if (sp != NULL)
642 mem_free (sp, nodesize);
643 *cpp = NULL;
645 return TRUE;
647 return FALSE;
649 #ifdef EXPORT_RPC_SYMBOLS
650 libc_hidden_def (xdr_bytes)
651 #else
652 libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0)
653 #endif
656 * Implemented here due to commonality of the object.
658 bool_t
659 xdr_netobj (XDR *xdrs, struct netobj *np)
662 return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ);
664 #ifdef EXPORT_RPC_SYMBOLS
665 libc_hidden_def (xdr_netobj)
666 #else
667 libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0)
668 #endif
671 * XDR a discriminated union
672 * Support routine for discriminated unions.
673 * You create an array of xdrdiscrim structures, terminated with
674 * an entry with a null procedure pointer. The routine gets
675 * the discriminant value and then searches the array of xdrdiscrims
676 * looking for that value. It calls the procedure given in the xdrdiscrim
677 * to handle the discriminant. If there is no specific routine a default
678 * routine may be called.
679 * If there is no specific or default routine an error is returned.
681 bool_t
682 xdr_union (XDR *xdrs,
683 /* enum to decide which arm to work on */
684 enum_t *dscmp,
685 /* the union itself */
686 char *unp,
687 /* [value, xdr proc] for each arm */
688 const struct xdr_discrim *choices,
689 /* default xdr routine */
690 xdrproc_t dfault)
692 enum_t dscm;
695 * we deal with the discriminator; it's an enum
697 if (!xdr_enum (xdrs, dscmp))
699 return FALSE;
701 dscm = *dscmp;
704 * search choices for a value that matches the discriminator.
705 * if we find one, execute the xdr routine for that value.
707 for (; choices->proc != NULL_xdrproc_t; choices++)
709 if (choices->value == dscm)
710 return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED);
714 * no match - execute the default xdr routine if there is one
716 return ((dfault == NULL_xdrproc_t) ? FALSE :
717 (*dfault) (xdrs, unp, LASTUNSIGNED));
719 libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0)
723 * Non-portable xdr primitives.
724 * Care should be taken when moving these routines to new architectures.
729 * XDR null terminated ASCII strings
730 * xdr_string deals with "C strings" - arrays of bytes that are
731 * terminated by a NUL character. The parameter cpp references a
732 * pointer to storage; If the pointer is null, then the necessary
733 * storage is allocated. The last parameter is the max allowed length
734 * of the string as specified by a protocol.
736 bool_t
737 xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
739 char *sp = *cpp; /* sp is the actual string pointer */
740 /* Initialize to silence the compiler. It is not really needed because SIZE
741 never actually gets used without being initialized. */
742 u_int size = 0;
743 u_int nodesize;
746 * first deal with the length since xdr strings are counted-strings
748 switch (xdrs->x_op)
750 case XDR_FREE:
751 if (sp == NULL)
753 return TRUE; /* already free */
755 /* fall through... */
756 case XDR_ENCODE:
757 if (sp == NULL)
758 return FALSE;
759 size = strlen (sp);
760 break;
761 case XDR_DECODE:
762 break;
764 if (!xdr_u_int (xdrs, &size))
766 return FALSE;
768 if (size > maxsize)
770 return FALSE;
772 nodesize = size + 1;
773 if (nodesize == 0)
775 /* This means an overflow. It a bug in the caller which
776 provided a too large maxsize but nevertheless catch it
777 here. */
778 return FALSE;
782 * now deal with the actual bytes
784 switch (xdrs->x_op)
786 case XDR_DECODE:
787 if (sp == NULL)
788 *cpp = sp = (char *) mem_alloc (nodesize);
789 if (sp == NULL)
791 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
792 return FALSE;
794 sp[size] = 0;
795 /* Fall through. */
797 case XDR_ENCODE:
798 return xdr_opaque (xdrs, sp, size);
800 case XDR_FREE:
801 mem_free (sp, nodesize);
802 *cpp = NULL;
803 return TRUE;
805 return FALSE;
807 #ifdef EXPORT_RPC_SYMBOLS
808 libc_hidden_def (xdr_string)
809 #else
810 libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0)
811 #endif
814 * Wrapper for xdr_string that can be called directly from
815 * routines like clnt_call
817 bool_t
818 xdr_wrapstring (XDR *xdrs, char **cpp)
820 if (xdr_string (xdrs, cpp, LASTUNSIGNED))
822 return TRUE;
824 return FALSE;
826 #ifdef EXPORT_RPC_SYMBOLS
827 libc_hidden_def (xdr_wrapstring)
828 #else
829 libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0)
830 #endif