Main Content

CWE Rule 134

Use of Externally-Controlled Format String

Since R2023a

Description

Rule Description

The software uses a function that accepts a format string as an argument, but the format string originates from an external source.

Polyspace Implementation

The rule checker checks for these issues:

  • Format string specifiers and arguments mismatch

  • Tainted string format

Examples

expand all

Issue

This issue occurs when the format specifiers in the formatted output functions such as printf do not match their corresponding arguments. For example, an argument of type unsigned long must have a format specification of %lu.

Risk

Mismatch between format specifiers and the corresponding arguments result in undefined behavior.

Fix

Make sure that the format specifiers match the corresponding arguments. For instance, in this example, the %d specifier does not match the string argument message and the %s specifier does not match the integer argument err_number.

  const char *message = "License not available";
  int err_number = ;-4
  printf("Error: %d (error type %s)\n", message, err_number);
Switching the two format specifiers fixes the issue. See the specifications for the printf function for more information about format specifiers.

In cases where integer promotion modifies the perceived data type of an argument, the analysis result shows both the original type and the type after promotion. The format specifier has to match the type after integer promotion.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example — Printing a Float
#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%d\n", fst);  //Noncompliant
}

In the printf statement, the format specifier, %d, does not match the data type of fst.

Correction — Use an Unsigned Long Format Specifier

One possible correction is to use the %lu format specifier. This specifier matches the unsigned integer type and long size of fst.

#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%lu\n", fst);
}
Correction — Use an Integer Argument

One possible correction is to change the argument to match the format specifier. Convert fst to an integer to match the format specifier and print the value 1.

#include <stdio.h>

void string_format(void) {

    unsigned long fst = 1;

    printf("%d\n", (int)fst);
}
Issue

This issue occurs when printf-style functions use a format specifier constructed from unsecure sources.

Risk

If you use externally controlled elements to format a string, you can cause buffer overflow or data-representation problems. An attacker can use these string formatting elements to view the contents of a stack using %x or write to a stack using %n.

Fix

Pass a static string to format string functions. This fix ensures that an external actor cannot control the string.

Another possible fix is to allow only the expected number of arguments. If possible, use functions that do not support the vulnerable %n operator in format strings.

Extend Checker

By default, Polyspace® assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider any data that does not originate in the current scope of Polyspace analysis as tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary.

Example — Get Elements from User Input
#include <stdio.h>
#include <unistd.h>
#define MAX 40
void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf(userstr);//Noncompliant   
}

This example prints the input argument userstr. The string is unknown. If it contains elements such as %, printf can interpret userstr as a string format instead of a string, causing your program to crash.

Correction — Print as String

One possible correction is to print userstr explicitly as a string so that there is no ambiguity.

#include "stdio.h"
#include <unistd.h>
#define MAX 40

void taintedstringformat(void) {
	char userstr[MAX];
	read(0,userstr,MAX);
	printf("%.20s", userstr); 
}

Check Information

Category: String Errors

Version History

Introduced in R2023a