Static Code Analysis using FlawFinder

Security in Software Application | Project 1

1. Introduction

This project involves using Flawfinder a static analysis tool, to scan a C code fragment for potential security vulnerabilities. The goal is to identify and address these flaws, demonstrating the tool’s effectiveness while highlighting the need for manual code review to catch any issues that may have been missed.

2. Tool Analysis

Strengths

Weakness

3. Code Fragment Overview

The code provided contains several syntax errors and the use of statements not present in the C language such as try/catch and the omission of some libraries.

Click to see source code

4. Flawfinder Output


Click to see the report in HTML

5. Analysis of Findings

6. Additional Vulnerabilities

These are additional vulnerabilities found through manual inspection:

7. Code Correction

The corrected code fragment after removing all vulnerabilities:


    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <unistd.h>  // for read()
    
    // Copying a String Safely
    void func1(char *src) {
    
        // length validation
        size_t src_len = strlen(src);
        if (src_len > 1023) {
            fprintf(stderr, "Error: input too large\n");
            return;
        }
        char dst[1024];  // fixed maximum buffer size to prevent overflow
        strncpy(dst, src, src_len);
        dst[src_len] = '\0';  // ensure null-termination
    }
    
    // Reading from a File Descriptor Safely
    void func2(int fd) {
        char *buf;
        size_t len;
        if (read(fd, &len, sizeof(len)) != sizeof(len)) {
            fprintf(stderr, "Error reading length\n");
            return;
        }
    
        if (len > 1024) {
            fprintf(stderr, "Error: data length exceeds buffer limit\n");
            return;
        }
    
        buf = (char *)malloc(len + 1);  // allocate buffer with an extra byte for null-termination
        if (buf == NULL) {
            fprintf(stderr, "Error: memory allocation failed\n");
            return;
        }
    
        if (read(fd, buf, len) != (ssize_t)len) {
            fprintf(stderr, "Error reading data\n");
            free(buf);
            return;
        }
        buf[len] = '\0';  // ensure null-termination
    
        free(buf);  // free allocated memory to avoid memory leaks
    }
    
    // Reading User Input with Bounds Checking
    void func3() {
        char buffer[1024];
        printf("Please enter your user ID: ");
        if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
            fprintf(stderr, "Error reading input\n");
            return;
        }
    
        if (!isalpha((unsigned char)buffer[0])) {
            char errormsg[1044];
            snprintf(errormsg, sizeof(errormsg), "%.1023s is not a valid ID", buffer);
            fprintf(stderr, "%s\n", errormsg);  // print error message securely
        }
    }
    
    // Buffer Allocation and Safe Copying
    void func4(char *foo) {
        size_t foo_len = strlen(foo);
        if (foo_len >= 10) {
            fprintf(stderr, "Error: input too large for buffer\n");
            return;
        }
        char *buffer = (char *)malloc(10 * sizeof(char));
        if (buffer == NULL) {
            fprintf(stderr, "Error: memory allocation failed\n");
            return;
        }
        strncpy(buffer, foo, 9);  // safely copy up to 9 characters
        buffer[9] = '\0';         // null-terminate to ensure safety
    
        free(buffer);  // free allocated memory
    }
    
    int main() {
        int y = 10;
        int a[10];
    
        func4("fooooooooooooooooooooooooooooooooooooooooooooooooooo");
    
        // Simplified error handling for non-C++ code
        func3();
    
        FILE *aFile = fopen("output.txt", "w");  // declare and open a file securely
        if (aFile == NULL) {
            fprintf(stderr, "Error opening file\n");
            return 1;
        }
    
        fprintf(aFile, "%s\n", "hello world");  // use safe file handling functions
        fclose(aFile);  // close file after writing to it
    
        while (y > 0) {
            if (y < 10) {
                a[y] = y;  // safely use within bounds
            }
            y--;
        }
    
        return 0;
    }
                

8. Conclusion

This project demonstrates the utility of Flawfinder in catching basic vulnerabilities while also showing the importance of manual review for deeper analysis.