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

Name: Potentially overrunning write with float to string conversion

Description: Buffer write operations that do not control the length of data written may overflow when floating point inputs take extreme values.

ID: cpp/overrunning-write-with-float

Kind: problem

Severity: error

Precision: medium

Query: OverrunWriteFloat.ql
/**
 * @name Potentially overrunning write with float to string conversion
 * @description Buffer write operations that do not control the length
 *              of data written may overflow when floating point inputs
 *              take extreme values.
 * @kind problem
 * @problem.severity error
 * @precision medium
 * @id cpp/overrunning-write-with-float
 * @tags reliability
 *       security
 *       external/cwe/cwe-120
 *       external/cwe/cwe-787
 *       external/cwe/cwe-805
 */
import semmle.code.cpp.security.BufferWrite

// see CWE-120UnboundedWrite.ql for a summary of CWE-120 violation cases

from BufferWrite bw, int destSize
where (not bw.hasExplicitLimit())                // has no explicit size limit
  and destSize = getBufferSize(bw.getDest(), _)
  and (bw.getMaxData() > destSize)               // and we can deduce that too much data may be copied
  and (bw.getMaxDataLimited() <= destSize)       // but it would fit without long '%f' conversions
select bw, "This '" + bw.getBWDesc() + "' operation may require " + bw.getMaxData() + " bytes because of float conversions, but the target is only " + destSize + " bytes."

The program performs a buffer copy or write operation that includes one or more float to string conversions (i.e. the %f format specifier), which may overflow the destination buffer if extreme inputs are given. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.

Recommendation

Always control the length of buffer copy and buffer write operations. strncpy should be used over strcpy, snprintf over sprintf, and in other cases 'n-variant' functions should be preferred.

Example

void displayValue(double value)
{
	char buffer[256];

	// BAD: extreme values may overflow the buffer
	sprintf(buffer, "%f", value);

	MessageBox(hWnd, buffer, "A Number", MB_OK);
}

In this example, the call to sprintf contains a %f format specifier. Though a 256 character buffer has been allowed, it is not sufficient for the most extreme floating point inputs. For example the representation of double value 1e304 (that is 1 with 304 zeroes after it) will overflow a buffer of this length.

To fix this issue three changes should be made:

  • Control the size of the buffer using a preprocessor define.
  • Replace the call to sprintf with snprintf, specifying the define as the maximum length to copy. This will prevent the buffer overflow.
  • Consider using the %g format specifier instead of %f.
References