FD_SET() macro does wrong integer shift when fd=31 (and others)

Originator:weissismail
Number:rdar://24586935 Date Originated:10-Feb-2016 02:50 PM
Status:Open Resolved:
Product:Developer Tools Product Version:Xcode 7.2 (7C68)
Classification:Crash/Hang/Data Loss Reproducible:Always
 
Summary:
FD_SET() left shifts an signed integer (int) by 31 if the fd==31 which is illegal and causes a crash if compiled with -fsanitize=shift

Steps to Reproduce:
1. Save the following C program as /tmp/wrong-shift.c

#include <sys/types.h>
#include <sys/select.h>

int main()
{
    int sock_fd=31;
    fd_set input = {{0}};
    FD_ZERO(&input);
    FD_SET(sock_fd, &input);
    return 0;
}

2. Compile it with
     clang -fsanitize=shift -fsanitize-undefined-trap-on-error -o /tmp/wrong-shift /tmp/wrong-shift.c
3. Run it with
     /tmp/wrong-shift

Expected Results:

Exits with exit code 0

Actual Results:

Prints 'Illegal instruction: 4', crashes with SIGILL and creates a crash report.

Regression:
don't know

Notes:

The Problem is given these macros

#define	FD_SET(n, p)	__DARWIN_FD_SET(n, p)
#define	__DARWIN_FD_SET(n, p)	do { int __fd = (n); ((p)->fds_bits[(unsigned long)__fd/__DARWIN_NFDBITS] |= ((__int32_t)(1<<((unsigned long)__fd % __DARWIN_NFDBITS)))); } while(0)

calling FD_SET(31, ...) will create an illegal shift ( 1<<((unsigned long)__fd % __DARWIN_NFDBITS) ) as the 1 is a signed integer (type int).

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!