Your example is just bad and exactly a reason why some people should avoid goto by all means.
First, a 'return' between allocating memory and cleaning up? Hello memory leaks!
Second, if you have a more complex program flow which allocates more 'bufs', do you really want 15 different gotos and labels)?
Do you, after 6 months, remember which 'buf' is allocated where and make changes? Even more so, do you think someone else finds your code easy to understand?
I don't mind gotos at all if used properly (e.g., cleanup) at all, so try this instead:
(allocate memory, etc)
if (shit_happens) goto cleanup;
if (buf1) free(
if (buf2) free(buf2);