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

Name: Uncontrolled format string

Description: Using externally-controlled format strings in printf-style functions can lead to buffer overflows or data representation problems.

ID: cpp/tainted-format-string

Kind: problem

Severity: warning

Precision: medium

Query: UncontrolledFormatString.ql
/**
 * @name Uncontrolled format string
 * @description Using externally-controlled format strings in
 *              printf-style functions can lead to buffer overflows
 *              or data representation problems.
 * @kind problem
 * @problem.severity warning
 * @precision medium
 * @id cpp/tainted-format-string
 * @tags reliability
 *       security
 *       external/cwe/cwe-134
 */

import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.FunctionWithWrappers
import semmle.code.cpp.security.TaintTracking

from PrintfLikeFunction printf, Expr arg, string printfFunction,
     Expr userValue, string cause
where
  printf.outermostWrapperFunctionCall(arg, printfFunction)
  and tainted(userValue, arg)
  and isUserInput(userValue, cause)
select arg,
  "The value of this argument may come from $@ and is being used as a formatting argument to " + printfFunction,
  userValue, cause

The program uses input from the user as a format string for printf style functions. This can lead to buffer overflows or data representation problems. An attacker can exploit this weakness to crash the program, disclose information or even execute arbitrary code.

The results of this rule do not include inputs from the user that are transferred through global variables. Those can be found in the related rule "Uncontrolled format string (through global variable)".

Recommendation

Use constant expressions as the format strings. If you need to print a value from the user, use printf("%s", value_from_user).

Example

#include <stdio.h>

void printWrapper(char *str) {
	printf(str);
}

int main(int argc, char **argv) {
	// This should be avoided
	printf(argv[1]);

	// This should be avoided too, because it has the same effect
	printWrapper(argv[1]);

	// This is fine
	printf("%s", argv[1]);
}

References