Skip to content

C memory safety rules (double-free, use-after-free) missing common exclusion patterns cause false positives #3770

@MarkLee131

Description

@MarkLee131

Describe the bug
Three C memory safety rules produce false positives on common, safe C patterns:

  1. double-free: Does not recognize return between two free() calls as separating mutually exclusive paths. Also only
    excludes malloc() reallocation but misses calloc(), realloc(), and strdup().

  2. use-after-free and function-use-after-free: Same missing calloc/realloc/strdup exclusions.

To Reproduce

  // False positive: double-free flags this, but return makes paths mutually exclusive
  int cleanup(int error) {
      char *buf = malloc(100);
      if (!error) {
          free(buf);
          return 0;
      }
      free(buf);  // <- flagged as double-free
      return -1;
  }

  // False positive: strdup reallocation not recognized
  char *var = strdup("hello");
  free(var);
  var = strdup("world");
  free(var);  // <- flagged as double-free

  // Same issue with calloc/realloc for use-after-free rules
  char *p = malloc(100);
  free(p);
  p = calloc(1, 200);
  p[0] = 'x';  // <- flagged as use-after-free

Runsemgrep --config r/c.lang.security.double-free (or use-after-free / function-use-after-free)
on the above code.

Expected behavior

These patterns should not be flagged:

  • Two free() calls separated by a return are mutually exclusive cleanup paths, not double-free
  • calloc/realloc/strdup between free and reuse is safe reallocation, same as malloc (which is already excluded)

Priority

  • P2: annoying but not blocking me

Desktop (please complete the following information):

  • OS: macOS (Darwin 25.3.0)
  • CLI tool
  • Version: semgrep 1.132.0

Additional context

Found while scanning Vim (~400k lines of C) with semgrep --config auto. The double-free rule's return gap caused false positives on
Vim's common goto-based error handling pattern where success and error paths each call free() but are separated by return. The missing
calloc/realloc/strdup exclusions affected all three rules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions