Bug#747123: Clang mistakenly removes an if check

Carlos Martín Nieto cmn at dwim.me
Mon May 5 19:12:56 UTC 2014


Package: clang-3.4

Hello,

We had an odd problem in our CI servers, where some builds would
mysteriously make a bunch of files read-only. After some wrangling, I
managed to track this down to the create mode being set to 0 when it
shouldn't be.

We have a function which wraps the system's open(2) for portability and
convenience, which needs to check if the flags include O_CREAT which
means that it should grab a third argument, to pass the file create mode
along.

We found that on release mode (which passes -O3 to clang, though it
seems that any optimisation mode triggers this bug), the check for the
'if' is skipped. Looking at the disassembly, it looks like the code for
inside the if-block is there, but the actual check for the flag is
skipped.

There is an issue on [1] with a description of what I found in the
context of trying to debug this in the project, but I have managed to
reduce it to a much simpler example, at the end of this message. If you
compile with `clang -O3 main.c` and run the code, you'll see that it
prints a mode of 0. Compiling without any optimisation options returns
the correct result.

This does not happen with clang-3.5 installed. I've also been unable to
reproduce this with a clang 3.4 built from svn (from the release tag).

[1] https://github.com/libgit2/libgit2/pull/2321#issuecomment-42039673

----8<----8<----

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>

int p_open(const char *path, int flags, ...)
{
	mode_t mode = 0;

	if (flags & O_CREAT) {
		va_list arg_list;

		va_start(arg_list, flags);
		mode = (mode_t)va_arg(arg_list, int);
		va_end(arg_list);
	}

	return mode;
}

int main(int argc, char **argv)
{
	int mode;

	mode = p_open("foo", O_CREAT, 0666);

	printf("mode %4o\n", mode);
	return 0;
}



More information about the Pkg-llvm-team mailing list