Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 4 Apr 2014 16:22:46 -0400
From: Morten Welinder <>
Subject: Re: printf issues

Another printf issue has shown up, this time with memory corruption.

    printf ("%.3E\n", 999999999.0);

The rounding test correctly decides that it needs to round this value
up to 1E+09.  It is, however, utterly unprepared for having nowhere to
put the carry.  It happily accesses and changes one or more elements
before the one that held 999999999.


On Fri, Apr 4, 2014 at 4:01 PM, Morten Welinder <> wrote:
> In fmt_fmt, the rounding decision is done using this test:
>             /* Decide whether to round by probing round+small */
>             if (round+small != round) { ...
> Why is this done with long double?
> The reason I ask is that the Valgrind situation improves a lot if
> this is done with doubles.
> (Valgrind situation: Valgrind emulates long doubles, poorly, by using
> simple doubles.  See, for example,
> Morten
> On Fri, Apr 4, 2014 at 2:54 PM, Szabolcs Nagy <> wrote:
>> * Morten Welinder <> [2014-04-04 13:42:30 -0400]:
>>> It looks like the LDBL_EPSILON version could be used in
>>>     roundl.c
>>>     modfl.c
>>>     ceill.c
>>>     floorl.c
>>> in the definition of TOINT instead of enumerating choices for
>>> LDBL_MANT_DIG.  It's basically the same thing going on
>> yes, that would be a bit nicer
>> (although other long double formats won't be supported anytime soon)
>> (note that in the future these implementations may need to change
>> the current versions raise inexact flag if result!=input, but the
>> next version of the floating-point extension standard for c
>> will require suppressing inexact, which i dont know how to do
>> with simple arithmetics efficiently without accessing the fenv..)
>>> While I was looking for that, I noticed that this modfl fallback looks
>>> problematic.  Even if long double and double are the same thing
>>> under the hood, I don't think you can cast pointers like that and
>>> assume it works.  It needs a temporary.
>>> #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
>>> long double modfl(long double x, long double *iptr)
>>> {
>>> return modf(x, (double *)iptr);
>>> }
>> yes, this is an aliasing violation, nice catch
>> the original idea was to allow tail call opt for these wrappers,
>> so they are a single branch instruction, we should fix it but
>> i think we can rely on that the ptr representations are the same:
>> long double modfl(long double x, long double *iptr)
>> {
>>         union {long double *ld; double *d;} u = {iptr};
>>         return modf(x, u.d);
>> }

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.