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

--- Comment #8 from Eric Gallager <egallager at gcc dot gnu.org> ---
(In reply to Neal H. Walfield from comment #0)
> I would like an attribute to indicate that ownership of an argument is moved
> to the function.  That is, any subsequent accesses to the variable should be
> considered invalid, and gcc should emit a warning, if possible.
> 
> Consider the following example:
> 
> ```
> #include <stdlib.h>
> #include <stdio.h>
> 
> int
> main(int argc, char *argv[]) {
>   int *a = malloc(sizeof(int));
>   *a = 1;
>   printf("%d\n", *a);
>   free(a);
>   printf("%d\n", *a);
> 
>   return 0;
> }
> ```
> 
> Compiling this with -Wall (using gcc 6.3.0-18+deb9u1 from Debian) does not
> emit a warning even though there is a use-after-free bug.
> 
> Although freeing a variable is the most obvious example of this pattern,
> this pattern often arises when dealing with pointers.
> 
> This RFE is based on my experience using Rust's lifetimes, which prevent
> this type of error in Rust.

I tested this with David Malcolm's static analyzer branch on Godbolt and it
catches it: https://godbolt.org/z/LWzGA5
Output:
<source>: In function 'main':

<source>:7:6: warning: dereference of possibly-NULL 'a' [CWE-690]
[-Wanalyzer-possible-null-dereference]

    7 |   *a = 1;

      |   ~~~^~~

  'main': events 1-2

    |

    |    6 |   int *a = malloc(sizeof(int));

    |      |            ^~~~~~~~~~~~~~~~~~~

    |      |            |

    |      |            (1) this call could return NULL

    |    7 |   *a = 1;

    |      |   ~~~~~~    

    |      |      |

    |      |      (2) 'a' could be NULL: unchecked value from (1)

    |

<source>:10:3: warning: use after 'free' of 'a' [CWE-416]
[-Wanalyzer-use-after-free]

   10 |   printf("%d\n", *a);

      |   ^~~~~~~~~~~~~~~~~~

  'main': events 1-4

    |

    |    6 |   int *a = malloc(sizeof(int));

    |      |            ^~~~~~~~~~~~~~~~~~~

    |      |            |

    |      |            (1) allocated here

    |    7 |   *a = 1;

    |      |   ~~~~~~    

    |      |      |

    |      |      (2) assuming 'a' is non-NULL

    |    8 |   printf("%d\n", *a);

    |      |   ~~~~~~~~~~~~~~~~~~

    |      |   |

    |      |   (3) freed here

    |    9 |   free(a);

    |   10 |   printf("%d\n", *a);

    |      |   ~~~~~~~~~~~~~~~~~~

    |      |   |

    |      |   (4) use after 'free' of 'a'; freed at (3)

    |

<source>:10:3: warning: use after 'free' of 'a' [CWE-416]
[-Wanalyzer-use-after-free]

   10 |   printf("%d\n", *a);

      |   ^~~~~~~~~~~~~~~~~~

  'main': event 1

    |

    |

Compiler returned: 0

Reply via email to