c.lang.security.function-use-after-free.function-use-after-free

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Variable '$VAR' was passed to a function after being freed. This can lead to undefined behavior.

Run Locally

Run in CI

Defintion

rules:
  - id: function-use-after-free
    patterns:
      - pattern-either:
          - pattern: $FUNC(..., <... $VAR ...>, ...)
          - pattern: $FUNC(..., <... $VAR->$ACCESSOR ...>, ...)
          - pattern: $FUNC(..., <... (*$VAR).$ACCESSOR ...>, ...)
          - pattern: $FUNC(..., <... $VAR[$NUM] ...>, ...)
      - metavariable-regex:
          metavariable: $FUNC
          regex: (?!^free$)
      - pattern-inside: free($VAR); ...
      - pattern-not-inside: free($VAR); ... $VAR = NULL; ...
      - pattern-not-inside: free($VAR); ... $VAR = malloc(...); ...
    message: Variable '$VAR' was passed to a function after being freed. This can
      lead to undefined behavior.
    metadata:
      cwe:
        - "CWE-416: Use After Free"
      references:
        - https://cwe.mitre.org/data/definitions/416.html
        - https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/use_after_free/
      category: security
      technology:
        - c
      confidence: LOW
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Memory Issues
    languages:
      - c
    severity: WARNING

Examples

function-use-after-free.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct name {
    char *myname;
    void (*func)(char *str);
} NAME;

void other_func(char *ignored) {}
void refreencode(char *ignored) {}

int bad_code1() {
    NAME *var;
    char buf[10];
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    // ruleid: function-use-after-free
    strcpy(buf, (char*)var);
    // ruleid: function-use-after-free
    other_func((char*)(*var));
    // ruleid: function-use-after-free
    other_func((char*)var[0]);
    // ruleid: function-use-after-free
    var->func(var->myname);
    return 0;
}

int bad_code2() {
    NAME *var;
    char buf[10];
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    // ruleid: function-use-after-free
    strcpy(buf, (char*)*var);
    // ruleid: function-use-after-free
    other_func((char*)var);
    // ruleid: function-use-after-free
    other_func((char*)var->myname);
    return 0;
}

int okay_code1() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    var = NULL;
    // This will segmentation fault
    // ok: function-use-after-free
    other_func((char*)var);
    other_func((char*)var->myname);
    other_func((char*)*var);
    return 0;
}

int okay_code2() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    var = NULL;
    var = (NAME *)malloc(sizeof(struct name));
    // This will segmentation fault
    // ok: function-use-after-free
    other_func((char*)var);
    other_func((char*)var->myname);
    other_func((char*)*var);
    return 0;
}