Hacker News new | past | comments | ask | show | jobs | submit login

Trivially safe? It can fail. As with snprintf, it's easy to forget to check the result, but at least with snprintf the result is always a safe string. With asprintf, not checking the result or doing it incorrectly will lead to undefined behaviour. From the man page:

> If memory allocation wasn't possible, or some other error occurs, these functions will return -1, and the contents of strp are undefined.




This is a dumb bug in the implementation. It should set dest to null on failure.


To be fair, dereferencing a null pointer is also UD in general rather than a guaranteed abort. (Some platforms may provide stronger guarantees, of course; many prevent pages from being mapped at 0x0 as a security mitigation.)


It's worse than this, as even on platforms where actually reading from 0x0 is a guaranteed abort, dereferencing a NULL pointer in C is still UB, meaning the compiler can assume it won't happen and optimize the program accordingly.

To take a rather convoluted example, if you dereference the pointer and then call a function that does a NULL check then writes to the pointer at some offset, it's possible that the compiler will in-line the function, then ellide the NULL check (since you've dereferenced it, the compiler assumes it's not NULL), then remove your dereference if it didn't have side-effects, so now the write goes through without any check. Granted, it would have to be a write to a massive offset to actually hit an allocated page, but I'm sure there are similar scenarios that are more realistic.


Well, yes, you need to check return codes. I file that under "trivial"; it's true of almost every function.


Although I agree with your general idea that asprintf() is the smarter choice, I think it's a stretch to call it trivially safe.

I think most people would call its API safe but not trivially safe, where trivial means "when I see that function called in other people's code, I don't need to pay attention to that call because it can't do anything crazy like cause undefined behaviour."

After all, if you include "as long as you check" in your definition of trivial, it is also trivial to check the parameters to strcpy() if you are using it right. And yet here we are, in a discussion about how that's a risk because it isn't used right.

If asprintf() terminated the program when it failed instead of leading on to undefined behaviour when unchecked, I'd call that trivially safe in a more pragmatic way. If you're going to ship a function for portability anyway, that's what I'd recommend. And in fact, that's what is used in software like GCC, called xasprintf() there. It returns the pointer or exits the program on allocation failure.


If asprintf() terminated the program when it failed instead of leading on to undefined behaviour when unchecked, I'd call that trivially safe in a more pragmatic way.

Ugh. Maybe in some contexts that's ok, but some of us write code which handles memory allocation failures with a bit more finesse than abort().


In most contexts aborting on malloc failure is OK, and preferable to trying to handle it gracefully, which has caused lots of problems, including security problems. On Linux you need to be running in a non-default configuration for malloc to be fallible in the first place (other than in trivial circumstances like attempting to request exabytes of memory in a single call).


Yeah, that's one of the things I don't like about Linux.


And some of us includes me.

But at the point where you're able to handle all memory allocation failures usefully, you're almost certainly doing something non-trivial to recover.

For example aborting some requested transaction, pruning items from your program's caches, delaying a subtask to release its temporary memory, or compressing some structures. At that point there's nothing "trivially" safe about a memory allocation.

Probably there are bugs in those recovery actions too. Even the obviously most simple recovery action of propagating an error return to abort a request: If that's a network request, just returning the error "sorry out of memory" is potentially going to fail. So you need recovery from the recovery path failing.




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

Search: