https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91951

            Bug ID: 91951
           Summary: goto + mixed declarations + cleanup attribute
                    considered harmful
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: allison.karlitskaya at redhat dot com
  Target Milestone: ---

Declaring a variable using __attribute__((__cleanup__)) and an initialiser and
then jumping over it with goto will produce code that runs the cleanup function
on the uninitialised variable (which will usually result in crashes when you
try to free an invalid pointer).

See
https://blog.fishsoup.net/2015/11/05/attributecleanup-mixed-declarations-and-code-and-goto/
for an old description of the essence of the problem.

This blog post implies that GCC gives a helpful warning about this problem, but
modern GCC versions seem to have lost this warning.  By comparison, clang gives
a warning and turns the goto itself into a hard error in response to detecting
the problem.

GCC should at least give a strong warning about this, or (even better) follow
the clang behaviour and error out.  An even better alternative would be to
ensure that the variable is initialised, even if the initialisation is skipped
over with goto.


desrt@x1:~$ gcc --version
gcc (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

desrt@x1:~$ cat test.c
#include <stdio.h>

static void
func (void **ptr)
{
  printf ("free(%p)\n", *ptr);
}

int
main (void)
{
  goto out;

  __attribute__((__cleanup__(func))) void *x = NULL;

out:
  return 0;
}

desrt@x1:~$ gcc -o test test.c -Wall -Wextra

desrt@x1:~$ ./test
free(0x559190032050)

desrt@x1:~$ clang -o test test.c -Wall -Wextra
test.c:14:44: warning: unused variable 'x' [-Wunused-variable]
  __attribute__((__cleanup__(func))) void *x = NULL;
                                           ^
test.c:12:3: error: cannot jump from this goto statement to its label
  goto out;
  ^
test.c:14:44: note: jump bypasses initialization of variable with
__attribute__((cleanup))
  __attribute__((__cleanup__(func))) void *x = NULL;
                                           ^
1 warning and 1 error generated.

desrt@x1:~$ clang --version
clang version 7.0.1-8 (tags/RELEASE_701/final)

Reply via email to