[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#751409: Same for ntoh*/hton*



Plamen Alexandrov wrote...

> Depending on the endian of the system, the macros le64toh(),
> be64toh(), htole64(), htobe64(), etc. could not return a 64-bit type.
> This can lead to issues ranging from compilation errors to runtime
> crashes.

Yepp, ran into crashes.

The same problem exists for the ntoh*/hton* functions in <in.h>. On big-
endian architectures, the input value is passed unchanged; on litte
endian it's capped to the respective size by __bswap_*

Reproducer:

======================================================================
#include <netinet/in.h>
#include <stdio.h>

int main (int argc, char **argv) {
    long l1 = 0x12345678;
    long l2 = ntohs (l1);
    printf ("Got: %08lx\n", l2);

    long long ll1 = 0x123456789abcdef;
    long long ll2 = ntohl (ll1);
    printf ("Got: %016llx\n", ll2);
}
======================================================================

Enable optimizations (-O2 -Wall) when building.

Result on amd64:

| Got: 00007856
| Got: 00000000efcdab89

Result on powerpc and ppc64:

| Got: 12345678
| Got: 0123456789abcdef

... which is out the domain for uint16_t and uint32_t resp.

My suggested fix is to mask the according bits:

@@ -393,10 +393,10 @@
 # if __BYTE_ORDER == __BIG_ENDIAN
 /* The host byte order is the same as network byte order,
    so these functions are all just identity.  */
-# define ntohl(x)      (x)
-# define ntohs(x)      (x)
-# define htonl(x)      (x)
-# define htons(x)      (x)
+# define ntohl(x)      ((x)&0xffffffff)
+# define ntohs(x)      ((x)&0xffff)
+# define htonl(x)      ((x)&0xffffffff)
+# define htons(x)      ((x)&0xffff)
 # else
 #  if __BYTE_ORDER == __LITTLE_ENDIAN
 #   define ntohl(x)    __bswap_32 (x)

This results in a consistent output:

| Got: 00005678
| Got: 0000000089abcdef

The worse part is gcc doesn't even raise warnings from this.

    Christoph

Attachment: signature.asc
Description: Digital signature


Reply to: