c.lang.security.insecure-use-printf-fn.insecure-use-printf-fn

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

Avoid using user-controlled format strings passed into 'sprintf', 'printf' and 'vsprintf'. These functions put you at risk of buffer overflow vulnerabilities through the use of format string exploits. Instead, use 'snprintf' and 'vsnprintf'.

Run Locally

Run in CI

Defintion

rules:
  - id: insecure-use-printf-fn
    message: Avoid using user-controlled format strings passed into 'sprintf',
      'printf' and 'vsprintf'. These functions put you at risk of buffer
      overflow vulnerabilities through the use of format string exploits.
      Instead, use 'snprintf' and 'vsnprintf'.
    metadata:
      cwe:
        - "CWE-134: Use of Externally-Controlled Format String"
      references:
        - https://doc.castsoftware.com/display/SBX/Never+use+sprintf%28%29+or+vsprintf%28%29+functions
        - https://www.cvedetails.com/cwe-details/134/Uncontrolled-Format-String.html
      category: security
      technology:
        - c
      confidence: LOW
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Improper Validation
    languages:
      - c
    severity: WARNING
    patterns:
      - pattern-either:
          - pattern: |
              $FUNC($BUFFER, argv[$NUM], ...);
              ...
              vsprintf(..., $BUFFER, ...);
          - pattern: vsprintf(..., argv[$NUM], ...)
          - pattern: |
              $FUNC($BUFFER, argv[$NUM], ...);
              ...
              sprintf(..., $BUFFER, ...);
          - pattern: sprintf(...,argv[$NUM],...)
          - pattern: |
              $FUNC($BUFFER, argv[$NUM], ...);
              ...
              printf(..., $BUFFER, ...);
          - pattern: printf(...,argv[$NUM],...)
      - metavariable-comparison:
          metavariable: $NUM
          comparison: int($NUM) > 0

Examples

insecure-use-printf-fn.c

#include <stdio.h>

void bad_vsprintf(int argc, char **argv) {
    char format[256];

    //ruleid: insecure-use-printf-fn
    strncpy(format, argv[1], 255);
    char buffer[100];
    vsprintf (buffer,format, args);

    //ruleid: insecure-use-printf-fn
    vsprintf(buffer, argv[1], args);

    //ok: insecure-use-printf-fn
    vsprintf("%s\n",argv[0]);

    //ok: insecure-use-printf-fn
    vsnprintf(buffer, format, args);
}

void bad_sprintf(int argc, char **argv) {
    char format[256];

    int a = 10, b = 20, c=30;
    //ruleid: insecure-use-printf-fn
    strcpy(format, argv[1]);
    char buffer[200];
    sprintf(buffer, format, a, b, c);


    char buffer[256];
    int i = 3;
    //ruleid: insecure-use-printf-fn
    sprintf(buffer, argv[2], a, b, c);

    //ok: insecure-use-printf-fn
    sprintf("%s\n",argv[0]);

    //ok: insecure-use-printf-fn
    snprintf(buffer, format, a,b,c);
}

void bad_printf() {
    //ruleid: insecure-use-printf-fn
    printf(argv[2], 1234);

    char format[300];
    //ruleid: insecure-use-printf-fn
    strcpy(format, argv[1]);
    printf(format, 1234);

    //ok: insecure-use-printf-fn
    printf("hello");

    //ok: insecure-use-printf-fn
    printf("%s\n",argv[0]);
}

int main() {
    bad_vsprintf(NULL);
    bad_sprintf();
    bad_printf();
    return 0;
}