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

Community Favorite
profile photo of semgrepsemgrep
Author
46,010
Download Count*

Variable '$VAR' was used after being freed. This can lead to undefined behavior.

Run Locally

Run in CI

Defintion

rules:
  - id: use-after-free
    patterns:
      - pattern-either:
          - pattern: $VAR->$ACCESSOR
          - pattern: (*$VAR).$ACCESSOR
          - pattern: $VAR[$NUM]
      - pattern-inside: free($VAR); ...
      - pattern-not-inside: $VAR = NULL; ...
      - pattern-not-inside: free($VAR); ... $VAR = malloc(...); ...
    message: Variable '$VAR' was used 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

use-after-free.c

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

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

void other_func(char *ignored) {}

int bad_code1() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    // ruleid: use-after-free
    var->func("use after free");
    return 0;
}

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

int bad_code2() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    // ruleid: use-after-free
    other_func(var->myname);
    return 0;
}

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

struct NAME {
  char first_name[32];
  int auth;
} s_auth;

int bad_code3(){
    struct NAME *var;
    var = malloc(sizeof(s_auth));
    free(var);
    // ruleid: use-after-free
    if(var->auth){
        printf("you have logged in already");
    }
    else{
        printf("you do not have the permision to log in.");
    }
    return 0;

}


int ok_code3(){
    struct NAME *var;
    var = malloc(sizeof(s_auth));
    free(var);
    var=NULL;
    // ok: use-after-free
    if(var->auth){
        printf("you have logged in already");
    }
    else{
        printf("you do not have the permision to log in.");
    }
    return 0;

}

struct lv {
    int length;
    char *value;
} lv;

struct lv2 {
    int length;
    struct lv *lv;
} lv2;


int bad_code4(){
    int initial = 1000;
    struct lv *lv = malloc(sizeof(*lv));
    lv->length = initial;
    lv->value = malloc(initial);
    free(lv);
    // ruleid: use-after-free
    free(lv->value);
    return 0;
}

int ok_code4(){
    int initial = 1000;
    struct lv *lv = malloc(sizeof(*lv));
    lv->length = initial;
    lv->value = malloc(initial);
    // ok: use-after-free
    free(lv->value);
    // ok: use-after-free
    free(lv);
    return 0;
}

int bad_code5(){
    int initial = 1000;
    struct lv *lv = malloc(sizeof(*lv));
    lv->length = initial;
    lv->value = malloc(initial);

    struct lv2 *lv2 = malloc(sizeof(*lv2));
    lv2->length = initial;
    lv2->lv = lv;
    // ok: use-after-free
    free(lv2->lv);
    // ruleid: use-after-free
    free(lv2->lv->value);
    // ok: use-after-free
    free(lv2);
    return 0;
}


int ok_code5(){
    int initial = 1000;
    struct lv *lv = malloc(sizeof(*lv));
    lv->length = initial;
    lv->value = malloc(initial);

    struct lv2 *lv2 = malloc(sizeof(*lv2));
    lv2->length = initial;
    lv2->lv = lv;
    // ok: use-after-free
    free(lv2->lv->value);
    // ok: use-after-free
    free(lv2->lv);
    // ok: use-after-free
    free(lv2);
    return 0;
}

int bad_code6() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    // ruleid: use-after-free
    (*var).func("use after free");
    return 0;
}

int ok_code6() {
    NAME *var;
    var = (NAME *)malloc(sizeof(struct name));
    free(var);
    var = (NAME *)malloc(sizeof(struct name));
    // ok: use-after-free
    (*var).func("use after free");
    return 0;
}


int bad_code7() {
    char *var;
    char buf[10];
    var = (char *)malloc(100);
    free(var);
    // ruleid: use-after-free
    char buf[0] = var[0];
    // todo rule/id: use-after-free	// todo
    strcpy(buf, var);
    return 0;
}