XDR Library and Short Enums
Andrey Simonenko
simon at comsys.ntu-kpi.kiev.ua
Tue Apr 24 09:37:12 UTC 2012
On Mon, Apr 16, 2012 at 02:28:50PM +0200, Sebastian Huber wrote:
> Hi,
>
> the XDR library implementation of xdr_enum() is currently:
>
> /*
> * XDR enumerations
> */
> bool_t
> xdr_enum(XDR *xdrs, enum_t *ep)
> {
> enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
>
> /*
> * enums are treated as ints
> */
> /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
> return (xdr_long(xdrs, (long *)(void *)ep));
> } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
> return (xdr_int(xdrs, (int *)(void *)ep));
> } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
> return (xdr_short(xdrs, (short *)(void *)ep));
> } else {
> return (FALSE);
> }
> }
>
> The enum_t is defined as:
>
> typedef int32_t enum_t;
>
> This is problematic with short enums (variable sized enums). I case of short
> enums sizeof (enum sizecheck) would be 1. The ARM EABI lets you a choice
> between two alternatives described in the document issued by ARM. See also
> section 7.1.3 "Enumerated Types"
>
> http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
>
> How would you implement and use the XDR library with short enums? The
> xdr_enum() can be easily changed to:
>
> /*
> * XDR enumerations
> */
> bool_t
> xdr_enum(XDR *xdrs, enum_t *ep)
> {
> /*
> * enums are treated as ints
> */
> /* LINTED */ if (sizeof (enum_t) == sizeof (long)) {
> return (xdr_long(xdrs, (long *)(void *)ep));
> } else /* LINTED */ if (sizeof (enum_t) == sizeof (int)) {
> return (xdr_int(xdrs, (int *)(void *)ep));
> } else /* LINTED */ if (sizeof (enum_t) == sizeof (short)) {
> return (xdr_short(xdrs, (short *)(void *)ep));
> } else {
> return (FALSE);
> }
> }
>
> The problem is in the XDR library usage. An example is this (rpc_msg.h):
>
> enum msg_type {
> CALL=0,
> REPLY=1
> };
>
> How would you fix this? What about
>
> enum msg_type {
> CALL=0,
> REPLY=1,
> _MSG_TYPE_INVALID = 0xffffffff
> };
>
RFC1832 and RFC4506 specify enumerations:
Enumerations have the same representation as signed integers.
Enumerations are handy for describing subsets of the integers.
and specify signed integers:
An XDR signed integer is a 32-bit datum that encodes an integer in
the range [-2147483648,2147483647].
Can somebody explain why xdr_enum() implementation has such logic
that does not correspond to the description of XDR enumeration type
in the above mentioned RFCs?
Another question. xdr_long() translates C 'long' integers to their
external representation. Actually it converts C 'long' integer to
uint32_t, obviously such conversion is incorrect.
Is is expected that the given value of 'long' type in xdr_long() will
fit to uint32_t type and is not negative?
Example:
-------------------------------------------------------------------
#include <err.h>
#include <stdio.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#define BUF_SIZE 1024
int
main(void)
{
char buf[BUF_SIZE] = {};
XDR xdrs1, xdrs2;
long x1, x2, y1, y2;
xdrmem_create(&xdrs1, buf, sizeof(buf), XDR_ENCODE);
xdrmem_create(&xdrs2, buf, sizeof(buf), XDR_DECODE);
x1 = 0x0123456789abcdefL;
x2 = -1;
if (xdr_long(&xdrs1, &x1) == FALSE || xdr_long(&xdrs1, &x2) == FALSE)
err(1, "xdr_long(xdrs1)");
if (xdr_long(&xdrs2, &y1) == FALSE || xdr_long(&xdrs2, &y2) == FALSE)
err(1, "xdr_long(xdrs2)");
printf("x1 = 0x%016lx\ny1 = 0x%016lx\n", x1, y1);
printf("x2 = %ld\ny2 = %ld\n", x2, y2);
return (0);
}
-------------------------------------------------------------------
Running it on amd64:
x1 = 0x0123456789abcdef
y1 = 0x0000000089abcdef
x2 = -1
y2 = 4294967295
More information about the freebsd-hackers
mailing list