1 --- gdtoaimp.h.orig 2010-01-29 16:43:20.000000000 -0800
2 +++ gdtoaimp.h 2010-02-01 10:58:41.000000000 -0800
5 #ifndef GDTOAIMP_H_INCLUDED
6 #define GDTOAIMP_H_INCLUDED
8 + * Paranoia: Protect exported symbols, including ones in files we don't
9 + * compile right now. The standard strtof and strtod survive.
12 +#define gdtoa __gdtoa
13 +#define freedtoa __freedtoa
14 +#define strtodg __strtodg
15 +#define g_ddfmt __g_ddfmt
16 +#define g_dfmt __g_dfmt
17 +#define g_ffmt __g_ffmt
18 +#define g_Qfmt __g_Qfmt
19 +#define g_xfmt __g_xfmt
20 +#define g_xLfmt __g_xLfmt
21 +#define strtoId __strtoId
22 +#define strtoIdd __strtoIdd
23 +#define strtoIf __strtoIf
24 +#define strtoIQ __strtoIQ
25 +#define strtoIx __strtoIx
26 +#define strtoIxL __strtoIxL
27 +#define strtord __strtord
28 +#define strtordd __strtordd
29 +#define strtorf __strtorf
30 +#define strtorQ __strtorQ
31 +#define strtorx __strtorx
32 +#define strtorxL __strtorxL
33 +#define strtodI __strtodI
34 +#define strtopd __strtopd
35 +#define strtopdd __strtopdd
36 +#define strtopf __strtopf
37 +#define strtopQ __strtopQ
38 +#define strtopx __strtopx
39 +#define strtopxL __strtopxL
41 +/* Protect gdtoa-internal symbols */
42 +#define Balloc __Balloc_D2A
43 +#define Bfree __Bfree_D2A
44 +#define ULtoQ __ULtoQ_D2A
45 +#define ULtof __ULtof_D2A
46 +#define ULtod __ULtod_D2A
47 +#define ULtodd __ULtodd_D2A
48 +#define ULtox __ULtox_D2A
49 +#define ULtoxL __ULtoxL_D2A
50 +#define any_on __any_on_D2A
51 +#define b2d __b2d_D2A
52 +#define bigtens __bigtens_D2A
53 +#define cmp __cmp_D2A
54 +#define copybits __copybits_D2A
55 +#define d2b __d2b_D2A
56 +#define decrement __decrement_D2A
57 +#define diff __diff_D2A
58 +#define dtoa_result __dtoa_result_D2A
59 +#define g__fmt __g__fmt_D2A
60 +#define gethex __gethex_D2A
61 +#define hexdig __hexdig_D2A
62 +#define hexdig_init_D2A __hexdig_init_D2A
63 +#define hexnan __hexnan_D2A
64 +#define hi0bits __hi0bits_D2A
65 +#define hi0bits_D2A __hi0bits_D2A
66 +#define i2b __i2b_D2A
67 +#define increment __increment_D2A
68 +#define lo0bits __lo0bits_D2A
69 +#define lshift __lshift_D2A
70 +#define match __match_D2A
71 +#define mult __mult_D2A
72 +#define multadd __multadd_D2A
73 +#define nrv_alloc __nrv_alloc_D2A
74 +#define pow5mult __pow5mult_D2A
75 +#define quorem __quorem_D2A
76 +#define ratio __ratio_D2A
77 +#define rshift __rshift_D2A
78 +#define rv_alloc __rv_alloc_D2A
79 +#define s2b __s2b_D2A
80 +#define set_ones __set_ones_D2A
81 +#define strcp __strcp_D2A
82 +#define strcp_D2A __strcp_D2A
83 +#define strtoIg __strtoIg_D2A
84 +#define sum __sum_D2A
85 +#define tens __tens_D2A
86 +#define tinytens __tinytens_D2A
87 +#define tinytens __tinytens_D2A
88 +#define trailz __trailz_D2A
89 +#define ulp __ulp_D2A
94 #ifdef Honor_FLT_ROUNDS
96 #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
102 +#include "libc_private.h"
103 +#include "spinlock.h"
108 #define MALLOC malloc
111 +#define INFNAN_CHECK
113 +#define NO_LOCALE_CACHE
116 #undef Avoid_Underflow
118 @@ -446,10 +538,14 @@
119 #define ALL_ON 0xffff
122 -#ifndef MULTIPLE_THREADS
123 -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
124 -#define FREE_DTOA_LOCK(n) /*nothing*/
126 +#define MULTIPLE_THREADS
127 +extern spinlock_t __gdtoa_locks[2];
128 +#define ACQUIRE_DTOA_LOCK(n) do { \
129 + if (__isthreaded) _SPINLOCK(&__gdtoa_locks[n]); \
131 +#define FREE_DTOA_LOCK(n) do { \
132 + if (__isthreaded) _SPINUNLOCK(&__gdtoa_locks[n]); \
138 #define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int))
139 #endif /* NO_STRING_H */
141 -#define Balloc Balloc_D2A
142 -#define Bfree Bfree_D2A
143 -#define ULtoQ ULtoQ_D2A
144 -#define ULtof ULtof_D2A
145 -#define ULtod ULtod_D2A
146 -#define ULtodd ULtodd_D2A
147 -#define ULtox ULtox_D2A
148 -#define ULtoxL ULtoxL_D2A
149 -#define any_on any_on_D2A
151 -#define bigtens bigtens_D2A
153 -#define copybits copybits_D2A
155 -#define decrement decrement_D2A
156 -#define diff diff_D2A
157 -#define dtoa_result dtoa_result_D2A
158 -#define g__fmt g__fmt_D2A
159 -#define gethex gethex_D2A
160 -#define hexdig hexdig_D2A
161 -#define hexnan hexnan_D2A
162 -#define hi0bits(x) hi0bits_D2A((ULong)(x))
164 -#define increment increment_D2A
165 -#define lo0bits lo0bits_D2A
166 -#define lshift lshift_D2A
167 -#define match match_D2A
168 -#define mult mult_D2A
169 -#define multadd multadd_D2A
170 -#define nrv_alloc nrv_alloc_D2A
171 -#define pow5mult pow5mult_D2A
172 -#define quorem quorem_D2A
173 -#define ratio ratio_D2A
174 -#define rshift rshift_D2A
175 -#define rv_alloc rv_alloc_D2A
177 -#define set_ones set_ones_D2A
178 -#define strcp strcp_D2A
179 -#define strtoIg strtoIg_D2A
181 -#define tens tens_D2A
182 -#define tinytens tinytens_D2A
183 -#define tinytens tinytens_D2A
184 -#define trailz trailz_D2A
187 extern char *dtoa_result;
188 extern CONST double bigtens[], tens[], tinytens[];
189 extern unsigned char hexdig[];
191 extern char *dtoa ANSI((double d, int mode, int ndigits,
192 int *decpt, int *sign, char **rve));
193 extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
194 - extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
195 + extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int, locale_t));
196 extern void hexdig_init_D2A(Void);
197 extern int hexnan ANSI((CONST char**, FPI*, ULong*));
198 extern int hi0bits_D2A ANSI((ULong));
200 extern char *strcp ANSI((char*, const char*));
201 extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
202 extern double strtod ANSI((const char *s00, char **se));
203 + extern double strtod_l ANSI((const char *s00, char **se, locale_t));
204 extern Bigint *sum ANSI((Bigint*, Bigint*));
205 extern int trailz ANSI((Bigint*));
206 extern double ulp ANSI((U*));
212 + * For very large strings, strtod and family might exhaust memory in tight
213 + * memory conditions (especially in 32-bits). Such large strings could also
214 + * tie up a CPU for minutes at a time. Either can be considered a denial-of-
215 + * service vunerability.
217 + * To fix, we limit the string size to the maximum we need to calculate the
218 + * rounding point correctly. The longest string corresponding to the exact
219 + * value of a floating point number occuring at 1.f...f p^-n, where n is
220 + * the (absolute value of the) smallest exponent for a normalize number.
222 + * To calculate this number of decimal digits, we use the formula:
224 + * (n + m) - int(n * log10(2)) + 3
226 + * where m is the number of bits in the f...f fraction. This is the number
227 + * of decimal digits for the least significant bit minus the number of leading
228 + * zeros for the most significant bit (the '1'), plus a few to compensate for
229 + * an extra digits due to the full 1.f...f value, an extra digit for the
230 + * mid-way point for rounding and an extra guard digit.
232 + * Using the approximation log10(2) ~ 1233 / (2^12), converting to the fpi.emin
233 + * and fpi.nbits values, we get:
235 + * -fpi.emin -((1233 * (-fpi.nbits - fpi.emin)) >> 12) + 3
237 + * Finally, we add an extra digit, either '1' or '0', to represent whether
238 + * to-be-truncated digits contain a non-zero digit, or are all zeros,
241 + * The truncated string is allocated on the heap, so code using
242 + * TRUNCATE_DIGITS() will need to free that space when no longer needed.
243 + * Pass a char * as the second argument, initialized to NULL; if its value
244 + * becomes non-NULL, memory was allocated.
246 +#define LOG2NUM 1233
247 +#define LOG2DENOMSHIFT 12
248 +#define TRUNCATEDIGITS(_nbits, _emin) (-(_emin) - ((LOG2NUM * (-(_nbits) - (_emin))) >> LOG2DENOMSHIFT) + 3)
250 +#define TRUNCATE_DIGITS(_s0, _temp, _nd, _nd0, _nf, _nbits, _emin, _dplen) \
252 + int _maxdigits = TRUNCATEDIGITS((_nbits), (_emin)); \
253 + if ((_nd) > _maxdigits && \
254 + ((_temp) = MALLOC(_maxdigits + (_dplen) + 2)) != NULL) { \
255 + char *_tp = (_temp) + _maxdigits; \
256 + if ((_nd0) >= _maxdigits) { \
257 + memcpy((_temp), (_s0), _maxdigits); \
258 + if ((_nd) > (_nd0)) *_tp++ = '1'; \
260 + const char *_q = (_s0) + _maxdigits; \
261 + int _n = (_nd0) - _maxdigits; \
262 + for(; _n > 0 && *_q == '0'; _n--, _q++) {} \
263 + *_tp++ = _n > 0 ? '1' : '0'; \
265 + (_nf) = -((_nd0) - (_maxdigits + 1)); \
266 + (_nd0) = _maxdigits + 1; \
268 + else if ((_nd0) == 0) { \
269 + memcpy((_temp), (_s0), _maxdigits); \
271 + (_nf) -= ((_nd) - (_maxdigits + 1)); \
274 + memcpy((_temp), (_s0), _maxdigits + (_dplen)); \
277 + (_nf) = (_maxdigits + 1) - (_nd0); \
280 + (_nd) = _maxdigits + 1; \
285 #endif /* GDTOAIMP_H_INCLUDED */