3

I am getting buffer overflow: Format String warning from hp fortify. Can you please let me know the maximum length a double value can have? In the following example dCode is a double value which is stored in pszPref.

Code:

TCHAR pszPref[64];
_stprintf(pszPref, "%f", dCode);

I just want to confirm the maximum length of dCode can have with or without decimal value.

Blacktempel
  • 3,935
  • 3
  • 29
  • 53
Tansheet
  • 79
  • 2
  • 5

4 Answers4

0

Due to the fact that the base 10 radix is often not the most natural representation of a floating point, there's no maximum string length: to display the exact floating point number could require an infinite number of base 10 digits.

Fortunately, for an IEEE754 floating point double, 15 significant figures are sufficient. If you write then read back a floating point double with that amount of precision then you'll get the same number back as the one you started with. (Use "%.15E" as the printf-style formatter.) Although the C++ standard does not insist on double being that type, it most frequently is, and on systems for which MFC is a target, it probably is.

You could test to be (almost) sure by checking std::numeric_limits<double>::is_iec559.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • So If we include the decimal value it can cross 64?? – Tansheet Oct 12 '15 at 07:20
  • Yup. But don't worry. 15 significant figures is sufficient. You'll need to use scientific notation though. See the amendments in this answer. – Bathsheba Oct 12 '15 at 07:20
  • No, you never need an "infinite number of base 10 digits". – Henrik Oct 12 '15 at 08:10
  • Oh yes you do. I can conjure up a floating point representation that is acceptable to the C++ standard that requires an infinite number. But in reality, the `is_iec559` check and 15 s.f. does the job. – Bathsheba Oct 12 '15 at 08:39
0

Since you don't give a precision argument for the format, printf and it's relatives use 6 decimal digits by default.

The minimum value of iee 754 double precision floating point is -1.7976931348623157E+308

To print that number with precision of 6 decimal digits, you need one character for sign, one for decimal point, 308 digits for the integral part and the 6 decimal digits for a total of 316 characters. Don't forget to allocate the extra character for null terminator. Therefore, an array of 317 characters should be sufficient but only if iee 754 is used, which is not guaranteed by the c++ standard.

hp fortify probably doesn't know that and it's not safe to assume iee 754 anyway, so you probably won't get rid of the warning no matter how big an array you use. To ensure that no overflow occurs, use snprintf or similar that allows passing the buffer size.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

While not exactly answering your question you could the use of char array by using std::to_string.

ie:

std::string strPref = std::to_string(dCode);

Note: If you are stuck on Visual Studio 2010 you will have to cast dCode as mentioned in this answer.

Community
  • 1
  • 1
graham.reeds
  • 16,230
  • 17
  • 74
  • 137
0

Fortify will produce that warning whenever you use the unbounded CRT string output methods (sprintf, strcpy, strcat etc) regardless of how large the target buffer actually is. In recent years Microsoft have produced 'secure' versions of all these methods that have an _s extension. e.g. _stprintf_s.

These methods improve over the truncating versions (snprintf etc) in that they call an error handler if overflow occurs. The truncating methods will not overflow a buffer but they could, in theory, be used to craft some invalid buffer content that causes knock-on errors that may be used as an attack vector by a hacker.

So, to secure your code and shut Fortify up:

  1. Call _set_invalid_parameter_handler (stdlib.h) with a callback method that handles overflow errors.

  2. Use _stprintf_s(pszPref, sizeof(pszPref)/sizeof(pszPref[0]), "%f", dCode).

Andy Brown
  • 11,766
  • 2
  • 42
  • 61
  • 1
    `_stprintf_s` expects the buffer size as the number of characters, not the size in bytes. Since Windows uses UTF-16 (and projects usually have `UNICODE` defined) you created the very buffer overflow you were trying to solve. Instead, use the function template, that can deduce the buffer size: `_stprintf_s(pszPref, _T("%f"), dCode);`. – IInspectable Oct 12 '15 at 18:11