I am learning C and in one of the tasks I am asked to use 1000 * getuid() + 0
to generate the semaphore name for sem_open
. There will be multiple semaphores and the last digit (+ 0
) is used to differentiate them.
Code snippet:
#define SEM_NAME_LENGTH 24
#define SEM_NAME 1000 * getuid() + 0
...
char sem_name[SEM_NAME_LENGTH];
/* convert the sem number (as defined in spec) to a string */
if (sprintf(sem_name, "%u", SEM_NAME) < 0) {
return -1;
}
sem_id = sem_open(sem_name, O_CREAT, S_IRUSR | S_IWUSR, 0);
It is evident that SEM_NAME
can exceed unsigned int
, because getuid
can return UINT_MAX
, and if we multiply that by 1000...
My first thought was to change the sprintf
format to "%llu"
, but then I get a warning:
format specifies type 'unsigned long long' but the argument has type 'unsigned int'
Which means that compilers are still considering the expression to be an unsigned int
or __uid_t
.
Looks like I have the following possibilities:
A. Manually typecast to unsigned long long
:
#define SEM_NAME (unsigned long long) 1000 * getuid() + 0
B. Define the name as variable:
unsigned long long sem_name = 1000 * getuid() + 0;
C. Check for overflows / not accept uids higher than UINT_MAX
/1000 (bad)
I am also quite surprised that compilers (gcc
, clang
) don't detect the problem themselves. I am using -std=gnu99 -Wall -Wextra -Wstrict-prototypes -pedantic
.