-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nvpair: inconsistent XDP packing of char types #14173
Comments
The question now is, what to do about this? I think the difference is harmless and the results are still compatible (but lack complete confidence in my knowledge of the C language math edge cases here). If so or if none of the various uses of |
After some discussion with @ahrens we've concluded this is a bug in the FreeBSD implementation of
|
Cast char's through unsigned char before storing as an integer in xdr_char(), this ensures that the encoded form is consistently not sign-extended following Open Solaris's example. Prior to this change, platforms with signed chars would sign extend values with the high bit set but ones with unsigned chars would not so 0xff would be stored as 0x000000ff on unsigned char platforms and 0xffffffff on signed char platforms. Decoding has the same result for either form so this is a largely cosmetic change, but it seems best to produce consistent output. For more discussion, see openzfs/zfs#14173 Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D37992
Cast char's through unsigned char before storing as an integer in xdr_char(), this ensures that the encoded form is consistently not sign-extended following Open Solaris's example. Prior to this change, platforms with signed chars would sign extend values with the high bit set but ones with unsigned chars would not so 0xff would be stored as 0x000000ff on unsigned char platforms and 0xffffffff on signed char platforms. Decoding has the same result for either form so this is a largely cosmetic change, but it seems best to produce consistent output. For more discussion, see openzfs/zfs#14173 Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D37992 (cherry picked from commit a872c37)
Cast char's through unsigned char before storing as an integer in xdr_char(), this ensures that the encoded form is consistently not sign-extended following Open Solaris's example. Prior to this change, platforms with signed chars would sign extend values with the high bit set but ones with unsigned chars would not so 0xff would be stored as 0x000000ff on unsigned char platforms and 0xffffffff on signed char platforms. Decoding has the same result for either form so this is a largely cosmetic change, but it seems best to produce consistent output. For more discussion, see openzfs/zfs#14173 Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D37992 (cherry picked from commit a872c37)
I've now committed a fix to FreeBSD |
Cast char's through unsigned char before storing as an integer in xdr_char(), this ensures that the encoded form is consistently not sign-extended following Open Solaris's example. Prior to this change, platforms with signed chars would sign extend values with the high bit set but ones with unsigned chars would not so 0xff would be stored as 0x000000ff on unsigned char platforms and 0xffffffff on signed char platforms. Decoding has the same result for either form so this is a largely cosmetic change, but it seems best to produce consistent output. For more discussion, see openzfs/zfs#14173 Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D37992
Cast char's through unsigned char before storing as an integer in xdr_char(), this ensures that the encoded form is consistently not sign-extended following Open Solaris's example. Prior to this change, platforms with signed chars would sign extend values with the high bit set but ones with unsigned chars would not so 0xff would be stored as 0x000000ff on unsigned char platforms and 0xffffffff on signed char platforms. Decoding has the same result for either form so this is a largely cosmetic change, but it seems best to produce consistent output. For more discussion, see openzfs/zfs#14173 Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D37992 (cherry picked from commit a872c37054172f3f7a03aef263ca5886a749771f)
System information
Describe the problem you're observing
The XDR packed output of 8-bit integer types is inconstant between architectures where
char
is signed (amd64, sparc) and ones where it is unsigned (aarch64). Specifically values greater than 127 are stored sign-extended on signed char architectures and zero-extended on unsigned char architectures. This is because all of them are encoded usingxdr_char()
which is (on FreeBSD which uses the Sun RPC implementation):It's arguably a bug that uint8 (
uint8_t
) values are being encoded this way. It's likewise probably a bug that int8 (int8_t
) types aren't being sign extended on signed architectures. Unfortunately there is no portablexdr_s_char()
orxdr_int8()
to go withxdr_u_char()
so we'd likely need to implement one.Describe how to reproduce the problem
On an aarch64 (or other unsigned char) system with #14160 applied to your openzfs tree, do a build and then, run:
You'll see the int8_array and uint8_array cases fail.
You can examine the difference in the packed output by creating an alternative set of reference files:
These are both XDR streams holding a 4-element int8_array with contents
{0,1,2,-1}
. With the one inbad-refs
being generated on an aarch64 system. The difference occurs in the last word of the line labeled00000030
.The text was updated successfully, but these errors were encountered: