Comment 15 for bug 1552913

Revision history for this message
David Mathog (mathog) wrote : Re: poppler in devlibs 61 breaks printf %lf

After a brief sojourn among the helpful denizens of the mingw mailing list I think I can explain the situation.

The short answer is that mingw does not completely conform to the C99 standard.

The long answer is:

For this code:

  double val=1.0;
  printf("%lf\n",val);

(1) With the default language setting the compiler passes "%lf\n" and a 64 bit double to _printf(). If nothing else is specified the linker uses a _printf() from MSVCRT. That library interprets the "%lf" to mean long double, which it takes to be 64 bit. So "1.0" is emitted. Accidentally it is the correct value, with the two mistakes (it isn't long double, long double isn't 64 bits) cancelling each other out.

(2) For the -std=c99 case the compiler still passes "%lf\n" and a 64 bit double, but in this case the function which receives it is provided by mingw. It also interprets "%lf" to mean long double. However it expects the value to be a gnu long double of 80 bits. Consequently it reads 80 bytes instead of 64, which results in the printing of an incorrect value. It can be so wrong that a huge string results, causing a buffer overflow, and a crash.

(3) When poppler is linked to an object prepared as in (1) something carried in the library causes the mingw variant of _printf() to be used and not the MSVCRT one, and again the wrong value is emitted, as in (2).

There is nothing wrong with our code other than it expects a fully C99 (or somewhat earlier) library, and that isn't the case in mingw. When I get a chance I will pull out the printf "%lf" parts, and that should resolve the issue no matter which printf mingw ends up using.

Other things to be aware of with respect to mingw in terms of compatibility with our other platforms:

1. %ll format is not supported. (Presumably %llu too.)

  http://www.mingw.org/wiki/c99

2. long doubles are not supported with printf. At present there is no way to print a gnu 80 bit long double within the mingw environment. Specify a long double and you may or may not get 80 bits for the calculation, depending on the compiler switches. Best to avoid these as long as we are using mingw as a base platform.

   http://stackoverflow.com/questions/7134547/gcc-printf-and-long-double-leads-to-wrong-output-c-type-conversion-messes-u

Keith Marshall in the mingw group says that the fix for the "%lf" problem, making it follow the ANSI standard with -std=c99 instead of whatever Microsoft does, is in their code tree but it isn't released yet. Unclear it that will also fix the "%ll". No fix for the long double issue is expected anytime soon.