Semmle 1.20
Skip to end of metadata
Go to start of metadata

Name: Buffer not sufficient for string

Description: A buffer allocated using 'malloc' may not have enough space for a string that is being copied into it. The operation can cause a buffer overrun. Make sure that the buffer contains enough room for the string (including the zero terminator).

ID: cpp/overflow-calculated

Kind: problem

Severity: warning

Query: OverflowCalculated.ql
/**
 * @name Buffer not sufficient for string
 * @description A buffer allocated using 'malloc' may not have enough space for a string that is being copied into it. The operation can cause a buffer overrun. Make sure that the buffer contains enough room for the string (including the zero terminator).
 * @kind problem
 * @id cpp/overflow-calculated
 * @problem.severity warning
 * @tags reliability
 *       security
 *       external/cwe/cwe-131
 *       external/cwe/cwe-120
 */
import cpp

class MallocCall extends FunctionCall
{
  MallocCall() { this.getTarget().hasQualifiedName("malloc") }

  Expr getAllocatedSize() {
    if this.getArgument(0) instanceof VariableAccess then
      exists(LocalScopeVariable v, ControlFlowNode def |
        definitionUsePair(v, def, this.getArgument(0)) and
        exprDefinition(v, def, result))
    else
      result = this.getArgument(0)
  }
}

predicate terminationProblem(MallocCall malloc, string msg)
{
  malloc.getAllocatedSize() instanceof StrlenCall and
  msg = "This allocation does not include space to null-terminate the string."
}

predicate spaceProblem(FunctionCall append, string msg)
{
  exists(MallocCall malloc, StrlenCall strlen, AddExpr add, FunctionCall insert, Variable buffer |
    add.getAChild() = strlen
    and exists(add.getAChild().getValue())
    and malloc.getAllocatedSize() = add
    and buffer.getAnAccess() = strlen.getStringExpr()
    and (insert.getTarget().hasQualifiedName("strcpy") or insert.getTarget().hasQualifiedName("strncpy"))
    and (append.getTarget().hasQualifiedName("strcat") or append.getTarget().hasQualifiedName("strncat"))
    and malloc.getASuccessor+() = insert
    and insert.getArgument(1) = buffer.getAnAccess()
    and insert.getASuccessor+() = append
    and msg = "This buffer only contains enough room for '" + buffer.getName() +
      "' (copied on line " + insert.getLocation().getStartLine().toString() + ")")
}

from Expr problem, string msg
where terminationProblem(problem, msg) or spaceProblem(problem, msg)
select problem, msg

This query finds calls to:

  • malloc that use a strlen for the buffer size and do not take the zero terminator into consideration.
  • strcat or strncat that use buffers that are too small to contain the new string.

The highlighted expression will cause a buffer overflow because the buffer is too small to contain the data being copied. Buffer overflows can result to anything from a segmentation fault to a security vulnerability (particularly if the array is on stack-allocated memory).

This check is an approximation, so some results may not be actual defects in the program. It is not possible in general to compute the exact value of the variable without running the program with all possible input data.

Recommendation

Increase the size of the buffer being allocated.

Example

This example includes three annotated calls that copy a string into a buffer. The first call to malloc creates a buffer that's the same size as the string, leaving no space for the zero terminator and causing an overflow. The second call to malloc correctly calculates the required buffer size. The call to strcat appends an additional string to the same buffer causing a second overflow.

void f(char* string) {
	// wrong: allocates space for characters, but not zero terminator
	char* buf = malloc(strlen(string));
	strcpy(buf, string);

	char* buf_right = malloc(strlen(string) + 1); //correct: includes the zero terminator
	strcpy(buf_right, string);
	// buf_right is now full
	strcat(buf_right, string); //wrong: appending would overflow the buffer
}

References
  • CWE-131: Incorrect Calculation of Buffer Size
  • I. Gerg. An Overview and Example of the Buffer-Overflow Exploit. IANewsletter vol 7 no 4. 2005.
  • M. Donaldson. Inside the Buffer Overflow Attack: Mechanism, Method & Prevention. SANS Institute InfoSec Reading Room. 2002.
  • Common Weakness Enumeration: CWE-131.
  • Common Weakness Enumeration: CWE-120.