Giter Club home page Giter Club logo

static-analyzer-c-rules's Introduction

static-analyzer-c-rules

Porting some rules from semgrep

name
----
insecure-use-gets-fn

description
-----------
Avoid 'gets()'. This function does not consider buffer boundaries and can lead
to buffer overflows. Use 'fgets()' or 'gets_s()' instead.

cwe
---
'CWE-676: Use of Potentially Dangerous Function'

references
----------
https://us-cert.cisa.gov/bsi/articles/knowledge/coding-practices/fgets-and-gets_s

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "gets") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid gets", "CRITICAL", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "gets_s");
            const fix = buildFix("Use fgets or gets_s", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
#include <stdio.h>

int DST_BUFFER_SIZE = 120;

int bad_code() {
    char str[DST_BUFFER_SIZE];
    // ruleid:insecure-use-gets-fn
    gets(str);
    printf("%s", str);
    return 0;
}

int main() {
    char str[DST_BUFFER_SIZE];
    // ok:insecure-use-gets-fn
    fgets(str);
    printf("%s", str);
    return 0;
}
name
----
insecure-use-printf-fn

description
-----------
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'.

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

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name
            arguments: (
              argument_list
              .
              [
                (identifier) 
                (subscript_expression
                    argument: (identifier) 
                    index: (number_literal)
                )
              ]
            )
            (#match? @fn_name "^(sprintf|printf|vsprintf)$")
          )

rule_code
---------
function visit(node, filename, code) {
            const functionName = node.captures["fn_name"];
            if (functionName) {
                const name = getCode(functionName.start, functionName.end, code);
                const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                    "Use of Externally-Controlled Format String", "WARNING", "security");
                addError(error);
            }
        }

violating code
--------------
#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;
}

name
----
insecure-use-memset

description
-----------
When handling sensitive information in a buffer, it's important to ensure 
that the data is securely erased before the buffer is deleted or reused. 
While `memset()` is commonly used for this purpose, it can leave sensitive 
information behind due to compiler optimizations or other factors. 
To avoid this potential vulnerability, it's recommended to use the 
`memset_s()` function instead. `memset_s()` is a standardized function 
that securely overwrites the memory with a specified value, making it more 
difficult for an attacker to recover any sensitive data that was stored in 
the buffer. By using `memset_s()` instead of `memset()`, you can help to 
ensure that your application is more secure and less vulnerable to exploits 
that rely on residual data in memory.

cwe
---
'CWE-14: Compiler Removal of Code to Clear Buffers'
    
references
----------
- https://cwe.mitre.org/data/definitions/14.html
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures/

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "memset") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid memset", "CRITICAL", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "memset_s");
            const fix = buildFix("Use memset_s", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
void badcode(char *password, size_t bufferSize) {
  char token[256];
  init(token, password);
  // ruleid: insecure-use-memset
  memset(password, ' ', strlen(password));
  // ruleid: insecure-use-memset
  memset(token, ' ', strlen(localBuffer));
  free(password);
}

void okcode(char *password, size_t bufferSize) {
  char token[256];
  init(token, password);
  // ok: insecure-use-memset
  memset_s(password, bufferSize, ' ', strlen(password));
  // ok: insecure-use-memset
  memset_s(token, sizeof(token), ' ', strlen(localBuffer));
  free(password);
}
name
----

insecure-use-string-copy-fn

description
-----------

Finding triggers whenever there is a strcpy or strncpy used.
This is an issue because strcpy does not affirm the size of the destination array
and strncpy will not automatically NULL-terminate strings.
This can lead to buffer overflows, which can cause program crashes
and potentially let an attacker inject code in the program.
Fix this by using strcpy_s instead (although note that strcpy_s is an
optional part of the C11 standard, and so may not be available).
 
cwe
---
- 'CWE-676: Use of Potentially Dangerous Function'
    
references
----------
- https://cwe.mitre.org/data/definitions/676
- https://nvd.nist.gov/vuln/detail/CVE-2019-11365

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "strcpy" || name == "strncpy") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid strcpy and strncpy", "WARNING", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "strcpy_s");
            const fix = buildFix("Use strcpy_s", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
#include <stdio.h>

int DST_BUFFER_SIZE = 120;

int bad_strcpy(src, dst) {
    n = DST_BUFFER_SIZE;
    if ((dst != NULL) && (src != NULL) && (strlen(dst)+strlen(src)+1 <= n))
    {
        // ruleid: insecure-use-string-copy-fn
        strcpy(dst, src);

        // ruleid: insecure-use-string-copy-fn
        strncpy(dst, src, 100);
    }
}

int main() {
   printf("Hello, World!");
   return 0;
}
name
----

insecure-use-strcat-fn

description
-----------

Finding triggers whenever there is a strcat or strncat used.
This is an issue because strcat or strncat can lead to buffer overflow vulns.
Fix this by using strcat_s instead.

cwe
---
- 'CWE-676: Use of Potentially Dangerous Function'
    
references
----------
- https://nvd.nist.gov/vuln/detail/CVE-2019-12553
- https://techblog.mediaservice.net/2020/04/cve-2020-2851-stack-based-buffer-overflow-in-cde-libdtsvc/

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "strcat" || name == "strncat") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid strcat and strncat", "WARNING", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "strcat_s");
            const fix = buildFix("Use strcat_s", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
#include <stdio.h>

int DST_BUFFER_SIZE = 120;

int bad_strcpy(src, dst) {
    n = DST_BUFFER_SIZE;
    if ((dst != NULL) && (src != NULL) && (strlen(dst)+strlen(src)+1 <= n))
    {
        // ruleid: insecure-use-strcat-fn
        strcat(dst, src);

        // ruleid: insecure-use-strcat-fn
        strncat(dst, src, 100);
    }
}

int main() {
   printf("Hello, World!");
   return 0;
}
name
----

insecure-use-strtok-fn

description
-----------
 
Avoid using 'strtok()'. This function directly modifies the first argument buffer,
permanently erasing the
delimiter character. Use 'strtok_r()' instead.
  
cwe
---
- 'CWE-676: Use of Potentially Dangerous Function'
    
references
----------
- https://wiki.sei.cmu.edu/confluence/display/c/STR06-C.+Do+not+assume+that+strtok%28%29+leaves+the+parse+string+unchanged
- https://man7.org/linux/man-pages/man3/strtok.3.html#BUGS
- https://stackoverflow.com/a/40335556

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "strtok") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid strtok", "WARNING", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "strtok_r");
            const fix = buildFix("Use strtok_r", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
#include <stdio.h>

int DST_BUFFER_SIZE = 120;

int bad_code() {
    char str[DST_BUFFER_SIZE];
    fgets(str, DST_BUFFER_SIZE, stdin);
    // ruleid:insecure-use-strtok-fn
    strtok(str, " ");
    printf("%s", str);
    return 0;
}

int main() {
    char str[DST_BUFFER_SIZE];
    char dest[DST_BUFFER_SIZE];
    fgets(str, DST_BUFFER_SIZE, stdin);
    // ok:insecure-use-strtok-fn
    strtok_r(str, " ", *dest);
    printf("%s", str);
    return 0;
}
}
name
----

insecure-use-scanf-fn

description
-----------
  
Avoid using 'scanf()'. This function, when used improperly, does not consider
buffer boundaries and can lead to buffer overflows. Use 'fgets()' instead
for reading input.

cwe
---
- 'CWE-676: Use of Potentially Dangerous Function'

references
----------
- http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html

tree_sitter_query
----------------- 
(call_expression
            function: (identifier) @fn_name)

rule_code
---------
function visit(node, filename, code) {
    const functionName = node.captures["fn_name"];
    if (functionName) {
        const name = getCode(functionName.start, functionName.end, code);
        if (name == "scanf") {
            const error = buildError(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col,
                "Avoid scanf", "WARNING", "security");
            const edit = buildEdit(functionName.start.line, functionName.start.col, functionName.end.line, functionName.end.col, "update", "fgets");
            const fix = buildFix("Use fgets", [edit]);
            addError(error.addFix(fix));
        }
    }
}

violating code
--------------
#include <stdio.h>

int DST_BUFFER_SIZE = 120;

int bad_code() {
    char str[DST_BUFFER_SIZE];
    // ruleid:insecure-use-scanf-fn
    scanf("%s", str);
    printf("%s", str);
    return 0;
}

int main() {
    char str[DST_BUFFER_SIZE];
    // ok:insecure-use-scanf-fn
    fgets(str);
    printf("%s", str);
    return 0;
}

static-analyzer-c-rules's People

Contributors

abhirag avatar

Stargazers

Sattva avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.