NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: vfprintf() issue of printing negative float value



In article 
<AANLkTikyD4CLr6x4d-dXP2PLFApLLfon3jM-PSNEUhtY%mail.gmail.com@localhost>,
nikunj badjatya  <nikunjbadjatya%gmail.com@localhost> wrote:
>Hi,
>
>I have found one issue in stdio module of NetBSD library while compiling it
>for
>ARMv7a (Cortex architecture) using the GNU GCC-4.5 toolchain.
>
>The issue is while printing negative float value and the float value
>greater than 9.0, vfprintf() prints malicious characters.
>
>This can be reproduce using the sample test as below:
>
>% Cat Sample_vfprintf.c
>{{{
>
>#include <stdio.h>
>#include <stdarg.h>
>
>
>void format (FILE * stream, char * format, ...)
>{
>  va_list args;
>  va_start (args, format);
>  vfprintf (stream, format, args);
>  va_end (args);
>}
>
>
>int main ()
>{
>   FILE * fp;
>
>   fp = fopen ("myfile.txt","w");
>   format (fp,"Call with %f \n",-3.14);
>   format (fp,"Call with %f \n",10.0);
>
>   fclose (fp);
>   return 0;
>}
>
>}}}
>
>
>The output on beagleboard target is:
>{{{
>-bash-3.2# ./sample_vfprintf
>
>-bash-3.2# cat myfile.txt
>
>Call with 0.,0000
>Call with :.000000
>}}}
>
>>From the above sample it is seen that for negative float value and the float
>value
>greater than 9.0, vfprintf() prints malicious characters.
>
>Later, I modified the optimization flag from O2 to O1 and build the NetBsd
>library
>and found the issue is resolved.
>
>On these lines further I have  analyzed and suspected this ?wrong
>optimization? may be cause
>due to ?strict aliasing?
>
>The man page of GNU GCC says about ?strict aliasing?:
>
>?-fstrict-aliasing
>           Allows the compiler to assume the strictest aliasing rules
>applicable to the language being compiled.
>          For C (and C++), this activates optimizations based on the type of
>expressions.  In particular, an
>         object of one type is assumed never to reside at the same address
>as an object of a different type,
>         unless the types are almost the same.  For example, an "unsigned
>int" can alias an "int", but not a
>         "void*" or a "double".  A character type may alias any other type.
>?
>
>
>To confirm this I have build NetBsd library using  ?-fno-strict-aliasing?
> flag with O2 optimization to suppress
>the ?strict aliasing? and found the above issue is resolved.
>
>
>Further I have investigated it in the NetBsd source and found the flow of
>vfprintf as below:
>
> Vfprintf()
>    ---> __vfprintf_unlocked
>        ---> cvt()
>           ---> __dtoa
>
>
>The dtoa() implementation in NetBsd as follows:
>
>$cat src/lib/libc/gdtoa/dtoa.c
>{{{
>
>148:        if (word0(d) & Sign_bit) {
>149:                /* set sign for everything, including 0's and NaNs */
>150:                *sign = 1;
>151:                word0(d) &= ~Sign_bit;  /* clear sign bit */
>152:                }
>
>}}}
>
>$cat src/lib/libc/gdtoa/gdtoaimp.h
>{{{
>176: #define ULong  uint32_t
>:
>278:
>279: typedef union { double d; ULong L[2]; } U;
>:
>291: #ifdef IEEE_LITTLE_ENDIAN
>292: #define word0(x) ( /* LINTED */ (U*)&x)->L[1]
>293: #define word1(x) ( /* LINTED */ (U*)&x)->L[0]
>
>}}}
>
>
>
>Since at line:292 its breaking the strict aliasing rule. So, to bypass this
>Aliasing rules I used ?__may_alias__? attribute as below.
>
>
>$cat src/lib/libc/gdtoa/gdtoaimp.h
>{{{
>- typedef union { double d; ULong L[2]; } U;
>+ typedef union { double d; ULong L[2]; } __attribute__((__may_alias__)) U;
>
>}}}
>
>With these changes vfprintf() is able to convert floating point number
>correctly without any issue.
>
>Please let me know if there are any issues.
>

Please file a PR...

Thanks,

christos


Home | Main Index | Thread Index | Old Index