nanobench icon indicating copy to clipboard operation
nanobench copied to clipboard

Failed to build with musl libc due to integer overflow in the argument for ioctl

Open erinacio opened this issue 2 years ago • 0 comments

This issue is found when trying to build nanobench latest bench and master commit on Alpine Linux (docker pull alpine:3.17) and a homemade musl toolchain on Arch Linux.

On Alpine Linux, a simple cmake <nanobench-dir> && make will show:

In file included from /tmp/nanobench/src/test/app/nanobench.cpp:2:
/tmp/nanobench/src/include/nanobench.h: In member function 'bool ankerl::nanobench::detail::LinuxPerformanceCounters::monitor(uint32_t, uint64_t, Target)':
/tmp/nanobench/src/include/nanobench.h:2679:25: error: overflow in conversion from 'long unsigned int' to 'int' changes value from '2148017159' to '-2146950137' [-Werror=overflow]
 2679 |     if (-1 == ioctl(fd, PERF_EVENT_IOC_ID, &id)) {
      |                         ^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[2]: *** [CMakeFiles/nb.dir/build.make:76: CMakeFiles/nb.dir/src/test/app/nanobench.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:186: CMakeFiles/nb.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

Clang has similar error message:

In file included from /tmp/nanobench/src/test/app/nanobench.cpp:2:
/tmp/nanobench/src/include/nanobench.h:2679:25: error: implicit conversion changes signedness: 'unsigned long' to 'int' [-Werror,-Wsign-conversion]
    if (-1 == ioctl(fd, PERF_EVENT_IOC_ID, &id)) {
              ~~~~~     ^~~~~~~~~~~~~~~~~
/usr/include/linux/perf_event.h:507:29: note: expanded from macro 'PERF_EVENT_IOC_ID'
#define PERF_EVENT_IOC_ID                       _IOR('$', 7, __u64 *)
                                                ^~~~~~~~~~~~~~~~~~~~~
/usr/include/bits/ioctl.h:8:21: note: expanded from macro '_IOR'
#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c))
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/bits/ioctl.h:1:52: note: expanded from macro '_IOC'
#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) )
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/nb.dir/build.make:76: CMakeFiles/nb.dir/src/test/app/nanobench.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:186: CMakeFiles/nb.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

After some investigation, turns out that this issue may be caused by glibc and musl using different signatures for ioctl. In glibc, ioctl is defined like (copied from Arch Linux /usr/include/sys/ioctl.h):

extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

while in musl libc:

int ioctl (int, int, ...);

PERF_EVENT_IOC_ID is evaluated to 2148017159 and thus overflows int, triggering -Woverflow.

Some Alpine Linux users already found this problem and reported it to musl. However, seems that musl maintainers were not willing to change it as that's exactly what POSIX specified.

erinacio avatar Mar 06 '23 13:03 erinacio