skip to Main Content

I ran the Fortify Static Code Analyzer on the ossec-hids repo and it reported the following "Buffer Overflow: Format String" finding for src/analysisd/stats.c:415:

The format string argument to fscanf() at stats.c line 415 does not properly limit the amount of data the function can write, which allows the program to write outside the bounds of allocated memory. This behavior could corrupt data, crash the program, or lead to the execution of malicious code

The line of code in question is like this:

if (fscanf(fp, "%d", &_RWHour[i][j]) <= 0) {

_RWHour is declared as

static int _RWHour[7][25];

on line 33 of the same file. I believe there is no shadowing of _RWHour between this declaration on line 33 and its use on line 415, as when I select the declaration on line 33, my IDE (Visual Studio 2019) highlights _RWHour in 415.

When I look at the cppreference documentation for fscanf, it says the following:

d matches a decimal integer. The format of the number is the same as expected by strtol with the value 10 for the base argument

The table I took the quote above from also shows that when no length modifier is used for %d (as is the case for the fscanf call in question), the argument type should be signed int* or unsigned int*.

My question is this:

Is it possible for the Fortify finding to be a false positive? Or is it possible to write to memory outside an int when you pass the address of an int to fscanf?

If it is possible to write outside the memory of an int when using %d with fscanf, how can this be safely avoided?

2

Answers


  1. fscanf(fp, "%d", &_RWHour[i][j]) is undefined behavior (UB)*1 if the numeric text attempts to convert to a value outside the int range.

    A quick fix to prevent UB is to limit the number of characters read with a width:

    //fscanf(fp, "%d", &_RWHour[i][j])
    fscanf(fp, "%4d", &_RWHour[i][j])  // Limit [-999 ... 9999].
    

    A more robust solution reads in the text and uses strtol() to convert.

    I recommend creating a helper function to handle reading in the int.

    This level of checking kinda stinks, doesn’t it?


    *1

    … or if the result of the conversion
    cannot be represented in the object, the behavior is undefined. C23dr § 7.23.6.2 10

    With UB, it is "possible to write to memory outside an int".

    Login or Signup to reply.
  2. Title: Can fscanf buffer overflow when using %d?


    Question:

    I am using fscanf in C to read integers from a file using the %d format specifier. I have heard about buffer overflows with scanf, but can fscanf also be vulnerable to buffer overflow when reading integers with %d? Should I be concerned about the safety of my code?

    Answer:

    The %d format specifier in fscanf is generally safe from buffer overflows when used correctly. It reads an integer value from the input and stores it into the provided variable.

    Unlike scanf, which reads from standard input (stdin), fscanf reads from a file stream, which can help mitigate some potential risks. When using fscanf with a file stream, the risk of buffer overflow is reduced because the data is read from a predefined file, rather than from user input.

    However, it’s important to ensure that your code handles potential errors or unexpected input appropriately. Here are a few points to consider:

    1. Buffer Size: Make sure the variable you are reading the integer into has sufficient space to accommodate the largest possible value. If the buffer size is not large enough, it could lead to undefined behavior, including buffer overflow.

    2. Input Validation: Validate the input to ensure it matches the expected format. If the input does not conform to the %d format specifier, the corresponding variable may not be updated correctly, potentially leading to unexpected behavior or uninitialized values.

    3. Return Value: Check the return value of fscanf to verify if the expected number of items were successfully read. If the return value differs from what you expect, handle the situation accordingly.

    By following these best practices and properly handling input and output, you can minimize the risk of buffer overflows or other unexpected behavior when using fscanf with the %d format specifier.

    Remember that while %d itself does not pose a significant buffer overflow risk, other format specifiers, such as %s for strings, can be vulnerable if not used carefully. Always be mindful of the data you are reading, the buffer sizes, and the overall security of your code.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search