Eric Blake <ebl...@redhat.com> writes: > On 08/04/2016 12:46 PM, Peter Maydell wrote: >> I've upgraded to a more recent version of clang, which now produces >> undefined-behaviour warnings for passing NULL pointers to some library >> functions. One of the things it has shown up is that some of the >> qtest tests ask for "memset" with size zero. In our current implementation >> this results in qtest.c calling g_malloc(0), which returns NULL, and > > I never understood why glib made that choice on g_malloc(0). I would > much prefer it to ALWAYS return something, just as glibc malloc(0) does.
I guess it made the choice because unlike malloc(0), it can't cause confusion. malloc() returning null can mean either error or nothing. The caller should pick nothing when it passed zero. g_malloc() returning null can only mean nothing. >> then calling memset(NULL, chr, 0), which is UB. > > Indeed, although I really wish POSIX could be loosened to say that the > source pointer is untouched if the length is 0 (I've debated about > filing a POSIX bug report to that effect, but have not done so yet), so > that the UB only happens when passing NULL with a non-zero size. For me, this is one of those pointless UBs, whose only effect on the real world is wasting programmer time. Seriously, what else could a sane memset(NULL, 0, 0) do? What could anyone gain from an insane memset() other than the glee of telling people "your program is wrong, and you're <insert derogatory word>!". The mission of this standard is to codify existing practice. Show me a real-world implementation of memset() that does something other than nothing when passed a zero size, and whose maintainers don't consider that a bug in need of fixing. >> So should we: >> (1) declare the qtest protocol commands 'memset', 'read', 'write' >> etc which operate on a lump of guest memory of specified size to >> support size == 0 as meaning "do nothing" > > My preference - even if we have to special case things to avoid UB at > the lower level, presenting well-defined behavior at the upper level is > easier to think about. > >> (2) declare that size == 0 is not valid and make it return a failure >> code back down the qtest pipe (and fix the offending tests) > > Doable, but not as fun to audit, and not my preference. Concur. We shouldn't slavishly replicate an underlying interface's complexities when we can just as well provide a more regular interface instead.