Skip to content

Portability review: unsafe uses of the long type (LLP64 vs LP64) #41

Description

@ngosang

Background

long has a platform-dependent width: 8 bytes on LP64 (Linux/macOS 64-bit) but
only 4 bytes on LLP64 (Windows 64-bit), and 4 bytes on 32-bit systems. This
causes three problem classes:

  1. Pointer truncation — casting a pointer to/from long loses the upper 32 bits on Win64.
  2. Overflow — values above 2³¹/2³² wrap when stored in a 4-byte long.
  3. Display/format truncation — file sizes shown via a too-narrow long.

This is the same class of bug already fixed in c86d7ad (wxListCtrl item-data →
wxUIntPtr) and 6c748aa (m_currentSearchwxUIntPtr).

Note: this report lists only confirmed issues. The bulk of long usage in
the tree was reviewed and found safe — CFormat/wxString::Format is type-safe
(it always formats with ll and ignores the user's length modifier, see
src/libs/common/Format.cpp:509), wxFileConfig stores integers as decimal text
(no binary width mismatch), the ed2k/EC binary protocol uses fixed-width
WriteUInt*/ReadUInt* types, and wxListCtrl item-data is already on wxUIntPtr.

Confirmed bugs (low impact, but real)

  • src/webserver/src/WebServer.cpp:1796size = ftell(f); into a long &size
    parameter. ftell returns long → truncates to 32-bit on Win64.
  • src/webserver/src/php_core_lib.cpp:622int size = ftell(f); truncates the
    long from ftell to int on every platform.
    Both only affect webserver template files, but should use off_t/int64.
  • src/TextClient.h:40unsigned long lFileSize; truncates the displayed
    size of files > 4 GB in the amulecmd text client on Win64 (formatted at
    src/TextClient.cpp:712). Should be uint64.

Fragile by convention (currently correct on LP64, wrong on Win64)

  • src/FileArea.cpp:120((unsigned long) info->si_addr) % gs_pageSize
    casts a pointer to unsigned long. POSIX-only path (USE_MMAP + sigaction),
    so it isn't compiled on Windows today, but should use uintptr_t.
  • src/libs/common/MuleDebug.cpp:324unsigned long address = (unsigned long)_address - s_pie_base;
    pointer → unsigned long in the bfd backtrace path (Linux-only). Should use uintptr_t.
  • src/InternalEvents.h:52-56,78SetExtraLong(long) / GetExtraLong() /
    long m_value. src/HTTPDownload.cpp:312 stores (long)expected (an expected
    download size) through it → truncates > 4 GB on Win64. Today it only carries IPs
    (uint32) and HTTP codes, but the type should be uint64/wxIntPtr.
  • src/PartFileConvert.cpp:278-281,328-330 — file index parsed through a long
    intermediate then cast (unsigned)l. Values are small in practice; better to use
    ToULong/uint32.

Cosmetic (no observable bug, but wrong type)

  • src/amule.h:375long webserver_pid; should be pid_t (logged with %ld
    at src/amule.cpp:270,273, passed to wxKill).
  • src/TerminationProcessAmuleweb.h:39long *m_webserver_pid; (same).
  • src/AppImageIntegration.cpp:301static_cast<long>(getpid()).

Suggested fix pattern

Follow c86d7ad / 6c748aa: replace long with wxUIntPtr/uintptr_t for
pointer-sized values, uint64/off_t for file sizes, and pid_t for process IDs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions