Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

On the contrary, you can do something safely with such a pointer - compare it with another pointer. If the value of 'alloca(0)' is _unspecified_, then this comparison is legal, and its result, while not specified, must be consistent. In other words, code like this should not fail the assertion:

  void *x = alloca(0);
  void *y;
  int is_x_null = (x == NULL);
  memcpy(&y, &x, sizeof(y)); // confuse the optimizer
  assert(is_x_null == (y == NULL));
Note that is_x_null can be either 0 or 1, and this value may even vary between runs. But it's not acceptable for the assert to fail here, and it sounds like it would with this bug.

If you argue that alloca(0) is 'undefined behavior', of course, all this goes out the window. Since alloca is not standardized, though, one can't really argue this - all of alloca's behavior is implementation-defined, and so if llvm-gcc really wants alloca(0) to be UB, it should document this fact as a porting concern.

Incidentally, all of this applies to malloc(0) as well. C99 defines malloc(0)'s behavior as follows:

> If the size of the space requested is zero, the behavior is implementation- defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

This is actually even stricter than 'unspecified', in that it requires the implementation to document which choice it takes.



Good point that you can compare the pointer with another pointer. However, your bit about consistency only applies to results from the same call. Nothing says that alloca(0) must return the same pointer on two different calls, and indeed one would naively expect the opposite. While one could certainly claim a compiler bug if the same value compared both equal to and not equal to NULL, that's not the case in the example given; instead, alloca(0) behaves as if it returns NULL in some cases, and non-NULL in other cases, which is completely allowed.

It's true that alloca is all implementation-defined, but do you know of an implementation where the value of alloca(0) is defined? On OS X, it is not defined.

Comparing alloca(0) to malloc(0) is off-base. The return value from malloc(0) has an important requirement that alloca(0) lacks: you must be able to pass the result to free(). Therefore, the compiler can't have it be an arbitrary value, whereas replacing all calls to alloca(0) with (void *)arc4random() would be (aside from the side effect of calling arc4random()) a valid transformation.


> instead, alloca(0) behaves as if it returns NULL in some cases, and non-NULL in other cases, which is completely allowed.

Not really. I can't reproduce the optimizer bug here (on the contrary, the optimizer in the version of llvm-gcc I have installed seems to assume it is null[1]), but if alloca() is returning null and the optimizer assumes it's non-null, the value will be treated as non-null in the function but null if, say, the value is passed into a non-inline function which compares it to null.

[1] i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)


The 'consistency' I speak of is the idea that, if I assign alloca(0) to a variable, it's either NULL or non-NULL - I can't look at that same variable two different ways and get different answers. From the sounds of the article, this requirement might be violated by this bug.


I don't think so. Only one comparison is being done in the example code. I'd bet that if you e.g. printed out the value of the pointer before the if statement, the optimization would no longer kick in as it does.


"On the contrary, you can do something safely with such a pointer - compare it with another pointer. If the value of 'alloca(0)' is _unspecified_, then this comparison is legal, and its result, while not specified, must be consistent."

While you would expect a comparison to another pointer to be legal, I don't believe it has to be consistent. That's the whole point of undefined behavior. In one sense, it's like the question of whether NaN == NaN. In many implementations, that expression is not necessarily true--even though based on your pointer example logic it should be.

Referencing the OP: the real problem here is not that the NULL check got optimized out and so seemed inconsistent. That's within the tolerance of C's undefined behavior (which is designed for optimizations like this and is what makes it so hard to write truly sane C code.) The real problem is a bug with the code as written. One should never check against and undefined result. Instead there should have been an initial boolean guard against the case of alloca'ing 0 bytes. I __could__ see an argument for expecting that to be always null (in fact, that's the argument for higher level languages!) But expecting it to be a specific value in relation to the stack? That seems arbitrary at best.


> While you would expect a comparison to another pointer to be legal, I don't believe it has to be consistent. That's the whole point of undefined behavior. In one sense, it's like the question of whether NaN == NaN. In many implementations, that expression is not necessarily true--even though based on your pointer example logic it should be.

Right, this is a question of whether alloca(0) is undefined behavior, an unspecified return value, or implementation-defined behavior. And I argue that alloca's behavior is implementation-defined in the first place, so it LLVM-gcc wants alloca(0) to be UB it needs to define that :)


"the case of alloca'ing 0 bytes. I __could__ see an argument for expecting that to be always null"

??? I would expect that it always succeeds. Rationale: if, at some time and place, alloca(n) succeeds, I expect that any alloca asking for less space would succeed, too.


so alloca(-1) would succeed too, right?


No. According to the OS X and Linux man pages 'size' has type 'size_t'. It is undefined whether size_t is signed.


alloca takes a sixe_t. I think size_t is unsigned. http://stackoverflow.com/questions/1089176/is-size-t-always-... seems to agree with that (correction welcome)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: