git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Beller <sbeller@google.com>
To: Jeff King <peff@peff.net>
Cc: "git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: [PATCH 10/10] add UNLEAK annotation for reducing leak false positives
Date: Tue, 5 Sep 2017 15:05:12 -0700	[thread overview]
Message-ID: <CAGZ79kYmZJ8k2=SVrx9vpEXoKhRBGwu8J=fS=cYiCLdKf+nDGA@mail.gmail.com> (raw)
In-Reply-To: <20170905130505.him3p4jhxp64r2vy@sigill.intra.peff.net>

On Tue, Sep 5, 2017 at 6:05 AM, Jeff King <peff@peff.net> wrote:

>   int main(void)

nit of the day:
  s/void/int argc, char *argv/ or in case we do not
  want to emphasize the argument list s/void//
  as that adds no uninteresting things.


>
> In other words, you can do:
>
>   int main(void)
>   {
>         char *p = some_function();
>         printf("%s", p);
>         UNLEAK(p);
>         return 0;
>   }
>
> to annotate "p" and suppress the leak report.

This sounds really cool so far.

After having a sneak peak at the implementation
it is O(1) in runtime for each added element, and the
space complexity is O(well).

> But wait, couldn't we just say "free(p)"? In this toy
> example, yes. But using UNLEAK() has several advantages over
> actually freeing the memory:

This is indeed the big question, that I have had.

>
>   1. It can be compiled conditionally. There's no need in
>      normal runs to do this free(), and it just wastes time.
>      By using a macro, we can get the benefit for leak-check
>      builds with zero cost for normal builds (this patch
>      uses a compile-time check, though we could clearly also
>      make it a run-time check at very low cost).
>
>      Of course one could also hide free() behind a macro, so
>      this is really just arguing for having UNLEAK(), not
>      for its particular implementation.

This is only a real argument in combination with (2), or in other
words you seem to hint at situations like these:

  struct *foo = obtain_new_foo();
  ...
  #if FREE_ANNOTATED_LEAKS
    /* special free() */
    release_foo(foo);
  #endif

With UNLEAK this situation works out nicely as we just
copy over all memory, ignoring elements allocated inside
foo, but for free() we'd have issues combining the preprocessor
magic with the special free implementation.

So how would we use syntactic sugar to made this
more comfortable? Roughly like

    MAYBE(release_foo(foo))

  #if (FREE_ANNOTATED_LEAKS)
  /* we rely on strict text substitution */
  /* as the function signature may change */
  #define MAYBE(fn) fn;
  #else
  #define MAYBE(fn)
  #endif

Me regurgitating this first argument is just a long way of saying
that it put me off even more after reading only the first argument.
Maybe reorder this argument to show up after the current second
argument, so the reader is guided better?

>   2. It's recursive across structures. In many cases our "p"
>      is not just a pointer, but a complex struct whose
>      fields may have been allocated by a sub-function. And
>      in some cases (e.g., dir_struct) we don't even have a
>      function which knows how to free all of the struct
>      members.
>
>      By marking the struct itself as reachable, that confers
>      reachability on any pointers it contains (including those
>      found in embedded structs, or reachable by walking
>      heap blocks recursively.
>
>   3. It works on cases where we're not sure if the value is
>      allocated or not. For example:
>
>        char *p = argc > 1 ? argv[1] : some_function();
>
>      It's safe to use UNLEAK(p) here, because it's not
>      freeing any memory. In the case that we're pointing to
>      argv here, the reachability checker will just ignore
>      our bytes.

This argument demonstrates why the MAYBE above is
inferior.

>
>   4. Because it's not actually freeing memory, you can
>      UNLEAK() before we are finished accessing the variable.
>      This is helpful in cases like this:
>
>        char *p = some_function();
>        return another_function(p);
>
>      Writing this with free() requires:
>
>        int ret;
>        char *p = some_function();
>        ret = another_function(p);
>        free(p);
>        return ret;
>
>      But with unleak we can just write:
>
>        char *p = some_function();
>        UNLEAK(p);
>        return another_function(p);

  5. It's not just about worrying if we can call UNLEAK
      once (in 4), but we also do not have to worry about
      calling it twice, or recursively. (This argument can be bad
      for cargo cult programmers, but we don't have these ;-)



> +#ifdef SUPPRESS_ANNOTATED_LEAKS
> +extern void unleak_memory(const void *ptr, size_t len);
> +#define UNLEAK(var) unleak_memory(&(var), sizeof(var));

As always with macros we have to be careful about its arguments.

  UNLEAK(a++)
  UNLEAK(baz())

won't work as intended.

  reply	other threads:[~2017-09-05 22:05 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-05 13:01 [PATCH 0/10] towards clean leak-checker output Jeff King
2017-09-05 13:03 ` [PATCH 01/10] test-lib: --valgrind should not override --verbose-log Jeff King
2017-09-05 13:04 ` [PATCH 02/10] test-lib: set LSAN_OPTIONS to abort by default Jeff King
2017-09-05 13:04 ` [PATCH 03/10] add: free leaked pathspec after add_files_to_cache() Jeff King
2017-09-05 13:04 ` [PATCH 04/10] update-index: fix cache entry leak in add_one_file() Jeff King
2017-09-05 13:04 ` [PATCH 05/10] config: plug user_config leak Jeff King
2017-09-05 13:04 ` [PATCH 06/10] reset: make tree counting less confusing Jeff King
2017-09-05 13:04 ` [PATCH 07/10] reset: free allocated tree buffers Jeff King
2017-09-05 13:04 ` [PATCH 08/10] repository: free fields before overwriting them Jeff King
2017-09-05 13:05 ` [PATCH 09/10] set_git_dir: handle feeding gitdir to itself Jeff King
2017-09-07 19:06   ` Brandon Williams
2017-09-05 13:05 ` [PATCH 10/10] add UNLEAK annotation for reducing leak false positives Jeff King
2017-09-05 22:05   ` Stefan Beller [this message]
2017-09-07  9:17     ` Jeff King
2017-09-07 20:38       ` Stefan Beller
2017-09-12 14:34     ` Kaartic Sivaraam
2017-09-12 15:05       ` Jeff King
2017-09-13  7:13         ` Kaartic Sivaraam
2017-09-06 17:16   ` Martin Ågren
2017-09-07  9:00     ` Jeff King
2017-09-12 13:41   ` Kaartic Sivaraam
2017-09-12 15:29     ` Jeff King
2017-09-13  6:44       ` Kaartic Sivaraam
2017-09-05 17:50 ` [PATCH 0/10] towards clean leak-checker output Martin Ågren
2017-09-05 19:02   ` Jeff King
2017-09-05 20:41     ` Martin Ågren
2017-09-06 12:39       ` Jeff King
2017-09-06  1:42     ` Junio C Hamano
2017-09-06 12:28       ` [PATCH 0/2] simplifying !RUNTIME_PREFIX Jeff King
2017-09-06 12:30         ` [PATCH 1/2] system_path: move RUNTIME_PREFIX to a sub-function Jeff King
2017-09-06 13:23           ` Johannes Schindelin
2017-09-06 13:27             ` Jeff King
2017-09-06 12:32         ` [PATCH 2/2] git_extract_argv0_path: do nothing without RUNTIME_PREFIX Jeff King
2017-09-08  6:38 ` [PATCH v2 10/10] add UNLEAK annotation for reducing leak false positives Jeff King
2017-09-19 20:45   ` Jonathan Tan
2017-09-19 21:03     ` Jeff King
2017-09-19 21:34       ` [PATCH for jk/leak-checkers] git-compat-util: make UNLEAK less error-prone Jonathan Tan
2017-09-19 21:46         ` Jeff King
2017-09-19 22:10           ` [PATCH for jk/leak-checkers v2] " Jonathan Tan
2017-09-20  1:45       ` [PATCH v2 10/10] add UNLEAK annotation for reducing leak false positives Junio C Hamano
2017-09-20  2:28         ` Jeff King
2017-09-20  5:12           ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGZ79kYmZJ8k2=SVrx9vpEXoKhRBGwu8J=fS=cYiCLdKf+nDGA@mail.gmail.com' \
    --to=sbeller@google.com \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).