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

Name: No space for zero terminator

Description: Allocating a buffer using 'malloc' without ensuring that there is always space for the entire string and a zero terminator can cause a buffer overrun.

ID: cpp/no-space-for-terminator

Kind: problem

Severity: error

Precision: high

Query: NoSpaceForZeroTerminator.ql
/**
 * @name No space for zero terminator
 * @description Allocating a buffer using 'malloc' without ensuring that
 *              there is always space for the entire string and a zero
 *              terminator can cause a buffer overrun.
 * @kind problem
 * @problem.severity error
 * @precision high
 * @id cpp/no-space-for-terminator
 * @tags reliability
 *       security
 *       external/cwe/cwe-131
 *       external/cwe/cwe-120
 *       external/cwe/cwe-122
 */
import cpp

class MallocCall extends FunctionCall {
  MallocCall() { this.getTarget().hasGlobalName("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."
}

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

This rule identifies calls to malloc that call strlen to determine the required buffer size, but do not allocate space for the zero terminator.

Recommendation

The expression highlighted by this rule creates a buffer that is of insufficient size to contain the data being copied. This makes the code vulnerable to buffer overflow which can result in anything from a segmentation fault to a security vulnerability (particularly if the array is on stack-allocated memory).

Increase the size of the buffer being allocated by one or replace malloc, strcpy pairs with a call to strdup

Example

void flawed_strdup(const char *input)
{
	char *copy;

	/* Fail to allocate space for terminating '\0' */
	copy = (char *)malloc(strlen(input));
	strcpy(copy, input);
	return copy;
}

References