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

Name: Potentially unsafe use of strcat

Description: Using 'strcat' without checking the size of the source string may result in a buffer overflow

ID: cpp/unsafe-strcat

Kind: problem

Severity: warning

Precision: medium

Query: UnsafeUseOfStrcat.ql
/**
 * @name Potentially unsafe use of strcat
 * @description Using 'strcat' without checking the size of the source string
 *              may result in a buffer overflow
 * @kind problem
 * @problem.severity warning
 * @precision medium
 * @id cpp/unsafe-strcat
 * @tags reliability
 *       correctness
 *       security
 *       external/cwe/cwe-676
 *       external/cwe/cwe-120
 *       external/cwe/cwe-251
 */
import cpp
import Buffer

/**
 * An access to a variable that is initialized by a constant
 * expression, and is never used as an lvalue anywhere else.
 */
predicate isEffectivelyConstAccess(VariableAccess a)
{
  exists(Variable v |
    a.getTarget() = v and
    v.getInitializer().getExpr().isConstant() and
    not v.getAnAccess().isUsedAsLValue()
  )
}

class StrcatSource extends VariableAccess {
  FunctionCall strcat;

  StrcatSource() {
    strcat.getTarget().hasName("strcat") and
    this = strcat.getArgument(1)
  }

  FunctionCall getStrcatCall() { result = strcat }
}

from StrcatSource src
where not src.getType() instanceof ArrayType and
      not exists(BufferSizeExpr bse |
        bse.getArg().(VariableAccess).getTarget() = src.getTarget()) and
      not isEffectivelyConstAccess(src)
select src.getStrcatCall(), "Always check the size of the source buffer when using strcat."

The standard library function strcat appends a source string to a target string. If you do not check the size of the source string then you cannot guarantee that appending the data to the target string will not cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability.

Recommendation

Check the highlighted function calls carefully to ensure that no buffer overflow is possible. For a more robust solution, consider adding explicit range checks or using the strncat function instead.

Example

void f(char *s) {
	char buf[80];
	strcpy(buf, "s: ");
	strcat(buf, s);  // wrong: buffer not checked before strcat
}

void g(char *s) {
	char buf[80];
	strcpy(buf, "s: ");
	if(strlen(s) < 77)
		strcat(buf, s);  // correct: buffer size checked before strcat
}

References
  • 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-676.
  • Common Weakness Enumeration: CWE-120.
  • Common Weakness Enumeration: CWE-251.