diff options
Diffstat (limited to 'newlib')
-rw-r--r-- | newlib/ChangeLog | 15 | ||||
-rw-r--r-- | newlib/libc/stdlib/mprec.h | 49 | ||||
-rw-r--r-- | newlib/libc/stdlib/strtod.c | 41 |
3 files changed, 47 insertions, 58 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog index c3e5a15d6..bc11fe183 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,18 @@ +2008-06-25 Hans-Peter Nilsson <hp@axis.com> + + Fix strict-aliasing issues with _strtod_r and Storeinc. + * libc/stdlib/strtod.c (_strtod_r): Change local variables aadj, + rv, rv0 from double to type U. Use accessor macros dval, dword0 + and dword1 for all accesses except for the ULtod call, where rv.i + replaces the pointer cast. + * libc/stdlib/mprec.h (U): Rename member L to i for easier re-use + of access macros. Tweak comment. + Remove #ifdef'd YES_ALIAS code. + (dword0, dword1, dval): Define in terms of uncast union member + access. Ditto for _DOUBLE_IS_32BITS variants. + (Storeinc): Replace aliasing-flawed microoptimized definition with + alternative suggested in comment. Remove now stale comment. + 2008-06-21 Corinna Vinschen <corinna@vinschen.de> * libc/include/machine/setjmp.h (_longjmp): Define as function on diff --git a/newlib/libc/stdlib/mprec.h b/newlib/libc/stdlib/mprec.h index 498de5b74..dea89bf11 100644 --- a/newlib/libc/stdlib/mprec.h +++ b/newlib/libc/stdlib/mprec.h @@ -78,31 +78,18 @@ union double_union #define word1(x) (x.i[1]) #endif - -/* The following is taken from gdtoaimp.h for use with new strtod. */ +/* The following is taken from gdtoaimp.h for use with new strtod, but + adjusted to avoid invalid type-punning. */ typedef __int32_t Long; -typedef union { double d; __ULong L[2]; } U; -#ifdef YES_ALIAS -#define dval(x) x -#ifdef IEEE_8087 -#define dword0(x) ((__ULong *)&x)[1] -#define dword1(x) ((__ULong *)&x)[0] -#else -#define dword0(x) ((__ULong *)&x)[0] -#define dword1(x) ((__ULong *)&x)[1] -#endif -#else /* !YES_ALIAS */ -#ifdef IEEE_8087 -#define dword0(x) ((U*)&x)->L[1] -#define dword1(x) ((U*)&x)->L[0] -#else -#define dword0(x) ((U*)&x)->L[0] -#define dword1(x) ((U*)&x)->L[1] -#endif -#define dval(x) ((U*)&x)->d -#endif /* YES_ALIAS */ +/* Unfortunately, because __ULong might be a different type than + __uint32_t, we can't re-use union double_union as-is without + further edits in strtod.c. */ +typedef union { double d; __ULong i[2]; } U; +#define dword0(x) word0(x) +#define dword1(x) word1(x) +#define dval(x) (x.d) #undef SI #ifdef Sudden_Underflow @@ -111,17 +98,7 @@ typedef union { double d; __ULong L[2]; } U; #define SI 0 #endif -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined (__IEEE_BYTES_LITTLE_ENDIAN) + defined (IEEE_8087) + defined (VAX) -#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ -((unsigned short *)a)[0] = (unsigned short)c, a++) -#else -#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ -((unsigned short *)a)[1] = (unsigned short)c, a++) -#endif +#define Storeinc(a,b,c) (*(a)++ = (b) << 16 | (c) & 0xffff) /* #define P DBL_MANT_DIG */ /* Ten_pmax = floor(P*log(2)/log(5)) */ @@ -167,11 +144,7 @@ typedef union { double d; __ULong L[2]; } U; #define word0(x) (x.i[0]) #define word1(x) 0 -#ifdef YES_ALIAS -#define dword0(x) ((__ULong *)&x)[0] -#else -#define dword0(x) ((U*)&x)->L[0] -#endif +#define dword0(x) word0(x) #define dword1(x) 0 #else diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c index 80e5aacef..703fbce1d 100644 --- a/newlib/libc/stdlib/strtod.c +++ b/newlib/libc/stdlib/strtod.c @@ -218,7 +218,8 @@ _DEFUN (_strtod_r, (ptr, s00, se), int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; _CONST char *s, *s0, *s1; - double aadj, aadj1, adj, rv, rv0; + double aadj, adj; + U aadj1, rv, rv0; Long L; __ULong y, z; _Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; @@ -286,7 +287,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), copybits(bits, fpi.nbits, bb); Bfree(ptr,bb); } - ULtod(((U*)&rv)->L, bits, exp, i); + ULtod(rv.i, bits, exp, i); }} goto ret; } @@ -469,7 +470,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + dval(rv) = -dval(rv); sign = 0; } #endif @@ -485,7 +486,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + dval(rv) = -dval(rv); sign = 0; } #endif @@ -513,7 +514,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { - rv = -rv; + dval(rv) = -dval(rv); sign = 0; } #endif @@ -976,14 +977,14 @@ _DEFUN (_strtod_r, (ptr, s00, se), } if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) - aadj = aadj1 = 1.; + aadj = dval(aadj1) = 1.; else if (dword1(rv) || dword0(rv) & Bndry_mask) { #ifndef Sudden_Underflow if (dword1(rv) == Tiny1 && !dword0(rv)) goto undfl; #endif aadj = 1.; - aadj1 = -1.; + dval(aadj1) = -1.; } else { /* special case -- power of FLT_RADIX to be */ @@ -993,24 +994,24 @@ _DEFUN (_strtod_r, (ptr, s00, se), aadj = 1./FLT_RADIX; else aadj *= 0.5; - aadj1 = -aadj; + dval(aadj1) = -aadj; } } else { aadj *= 0.5; - aadj1 = dsign ? aadj : -aadj; + dval(aadj1) = dsign ? aadj : -aadj; #ifdef Check_FLT_ROUNDS switch(Rounding) { case 2: /* towards +infinity */ - aadj1 -= 0.5; + dval(aadj1) -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ - aadj1 += 0.5; + dval(aadj1) += 0.5; } #else if (Flt_Rounds == 0) - aadj1 += 0.5; + dval(aadj1) += 0.5; #endif /*Check_FLT_ROUNDS*/ } y = dword0(rv) & Exp_mask; @@ -1020,7 +1021,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { dval(rv0) = dval(rv); dword0(rv) -= P*Exp_msk1; - adj = aadj1 * ulp(dval(rv)); + adj = dval(aadj1) * ulp(dval(rv)); dval(rv) += adj; if ((dword0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { @@ -1042,18 +1043,18 @@ _DEFUN (_strtod_r, (ptr, s00, se), if ((z = aadj) <= 0) z = 1; aadj = z; - aadj1 = dsign ? aadj : -aadj; + dval(aadj1) = dsign ? aadj : -aadj; } dword0(aadj1) += (2*P+1)*Exp_msk1 - y; } - adj = aadj1 * ulp(dval(rv)); + adj = dval(aadj1) * ulp(dval(rv)); dval(rv) += adj; #else #ifdef Sudden_Underflow if ((dword0(rv) & Exp_mask) <= P*Exp_msk1) { dval(rv0) = dval(rv); dword0(rv) += P*Exp_msk1; - adj = aadj1 * ulp(dval(rv)); + adj = dval(aadj1) * ulp(dval(rv)); dval(rv) += adj; #ifdef IBM if ((dword0(rv) & Exp_mask) < P*Exp_msk1) @@ -1076,7 +1077,7 @@ _DEFUN (_strtod_r, (ptr, s00, se), dword0(rv) -= P*Exp_msk1; } else { - adj = aadj1 * ulp(dval(rv)); + adj = dval(aadj1) * ulp(dval(rv)); dval(rv) += adj; } #else /*Sudden_Underflow*/ @@ -1088,11 +1089,11 @@ _DEFUN (_strtod_r, (ptr, s00, se), * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - aadj1 = (double)(int)(aadj + 0.5); + dval(aadj1) = (double)(int)(aadj + 0.5); if (!dsign) - aadj1 = -aadj1; + dval(aadj1) = -dval(aadj1); } - adj = aadj1 * ulp(dval(rv)); + adj = dval(aadj1) * ulp(dval(rv)); dval(rv) += adj; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ |