Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#4556 closed Bug (fixed)

Transmission 2.40 fails to connect with UDP trackers on big endian systems

Reported by: unknown Owned by: jordan
Priority: Normal Milestone: 2.42
Component: libtransmission Version: 2.40
Severity: Normal Keywords: UDP tracker big endian connect fail
Cc:

Description

This bug is caused by the implementation of tr_htonll and tr_ntohll (both located at libtransmission/utils.c) for systems without htonll and ntohll native implementation.

uint64_t
tr_htonll( uint64_t x )
{
#ifdef HAVE_HTONLL
    return htonll( x );
#else
    /* fallback code by Runner and Juan Carlos Cobas at
     * http://www.codeproject.com/KB/cpp/endianness.aspx */
    return (((uint64_t)(htonl((int)((x << 32) >> 32))) << 32) |
                     (unsigned int)htonl(((int)(x >> 32))));
#endif
}

uint64_t
tr_ntohll( uint64_t x )
{
#ifdef HAVE_NTOHLL
    return ntohll( x );
#else
    /* fallback code by Runner and Juan Carlos Cobas at
     * http://www.codeproject.com/KB/cpp/endianness.aspx */
    return (((uint64_t)(ntohl((int)((x << 32) >> 32))) << 32) |
                     (unsigned int)ntohl(((int)(x >> 32))));
#endif
}

On big endian systems the host and network byteorder do not differ, but the current implementation do not check the endianness, thus byteswapping the 64-bit integer even on big endian systems, which is erroneous.

I have made a simple program to test the bug.

Output (little endian system):

NOTICE: System is little endian; host and network byteorder differ
Testing number: 0x1980
=> htons      : 0x8019
Testing number: 0x27101980
=> htonl      : 0x80191027
Testing number: 0x41727101980
=> tr_htonll  : 0x8019102717040000

Output (big endian system):

NOTICE: System is big endian; host and network byteorder do not differ
Testing number: 0x1980
=> htons      : 0x1980
Testing number: 0x27101980
=> htonl      : 0x27101980
Testing number: 0x41727101980
=> tr_htonll  : 0x2710198000000417

Note that tr_htonll(0x41727101980) != 0x41727101980 on a big endian system, which is incorrect.

Therefore, the byteswapping should be done only if the system is little endian.

Attachments (3)

endian-test.c (1.6 KB) - added by unknown 10 years ago.
Sample program to test tr_htonll/tr_ntohll
endian-test-02.c (2.5 KB) - added by unknown 10 years ago.
Sample program to test tr_htonll/tr_ntohll (with htonll/ntohll implementation from the link provided at comment # 1)
fix-tr_htonll-tr_ntohll-be.patch (1.4 KB) - added by unknown 10 years ago.

Download all attachments as: .zip

Change History (11)

Changed 10 years ago by unknown

Sample program to test tr_htonll/tr_ntohll

comment:1 follow-up: Changed 10 years ago by jordan

Thanks for reporting this issue.

I'm thinking of using http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 as a replacement implementation. Could you confirm whether or not that implementation works on your big-endian system?

Changed 10 years ago by unknown

Sample program to test tr_htonll/tr_ntohll (with htonll/ntohll implementation from the link provided at comment # 1)

comment:2 in reply to: ↑ 1 Changed 10 years ago by unknown

Replying to jordan:

Thanks for reporting this issue.

I'm thinking of using http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c/875505#875505 as a replacement implementation. Could you confirm whether or not that implementation works on your big-endian system?

I have tested the code of the link and works on both systems.

Output (little endian system):

NOTICE: System is little endian; host and network byteorder differ
Testing number: 0x1980
=> htons      : 0x8019
=> ntohs      : 0x8019
Testing number: 0x27101980
=> htonl      : 0x80191027
=> ntohl      : 0x80191027
Testing number: 0x41727101980
=> tr_htonll  : 0x8019102717040000
=> tr_ntohll  : 0x8019102717040000

Output (big endian system):

NOTICE: System is big endian; host and network byteorder do not differ
Testing number: 0x1980
=> htons      : 0x1980
=> ntohs      : 0x1980
Testing number: 0x27101980
=> htonl      : 0x27101980
=> ntohl      : 0x27101980
Testing number: 0x41727101980
=> tr_htonll  : 0x41727101980
=> tr_ntohll  : 0x41727101980

Changed 10 years ago by unknown

comment:3 Changed 10 years ago by unknown

Patch included. I have changed the code from link at comment:1 a bit:

unsigned long long => uint64_t
unsigned long => uint32_t
(l|ll)v => (l|ll)x

NOTE: The patch has been tested only on 32-bit systems (both little and big endian).

comment:4 Changed 10 years ago by jordan

Confirmed working on a 64-bit little endian system, too.

comment:5 Changed 10 years ago by jordan

  • Milestone changed from None Set to 2.50
  • Status changed from new to assigned

comment:6 Changed 10 years ago by jordan

  • Keywords backport-2.4x added
  • Resolution set to fixed
  • Status changed from assigned to closed

Fixed in r12981.

comment:7 Changed 10 years ago by jordan

  • Milestone changed from 2.50 to 2.42

backported to the 2.4x/ branch for 2.42 by r13002

comment:8 Changed 10 years ago by jordan

  • Keywords backport-2.4x removed
Note: See TracTickets for help on using tickets.