Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <3E13C1E1.1000103@ece.gatech.edu> Date: Wed, 01 Jan 2003 23:36:49 -0500 From: Charles Wilson User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 X-Accept-Language: en-us, en MIME-Version: 1.0 To: cygwin AT cygwin DOT com Subject: Re: Heads up: *possible* bug in cygwin References: <3E05BD05 DOT 5090408 AT ece DOT gatech DOT edu> <3E0DDE19 DOT 1060903 AT ece DOT gatech DOT edu> <3E10A7AE DOT 20405 AT ece DOT gatech DOT edu> <3E10C29B DOT 2010709 AT ece DOT gatech DOT edu> <3E111AAF DOT 3090008 AT ece DOT gatech DOT edu> <20021231043913 DOT GA26944 AT redhat DOT com> <3E11AD26 DOT 8050506 AT ece DOT gatech DOT edu> <20021231175349 DOT GC6542 AT redhat DOT com> <3E123A28 DOT 8030705 AT ece DOT gatech DOT edu> <1041383123 DOT 6526 DOT 13 DOT camel AT lifelesswks> <3E137A39 DOT 9050204 AT ece DOT gatech DOT edu> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Turns out, the problem IS in newlib. > First, create a buffer of the appropriate length: > buffer = g_new (gchar, g_printf_string_upper_bound (format, args1)); > > And then format the data into that buffer. > vsprintf (buffer, format, args2); > > But the buffer isn't long enough, so the actual problem is *probably* > somewhere in the g_printf_string_upper_bound() routine, that computes > the appropriate length. Well, not exactly. g_printf_string_upper_bound returns 30k, which is more than sufficient, actually. An annotated "stack trace" is below. (ignore the stuff about impure_ptr, I wrote that stuff when I thought there was a problem with insuffient memory allocation in that structure, as used by *printf. I was both right and wrong, but impure_ptr is not the problem...) vsprintf initializes a FILE variable f. Sets f._data = _impure_ptr calls vfprintf(&f, ....) vfprintf makes sure f is good (which it will be, in this case) calls _vfprintf_r(f->_data, ...) which is simply _vfprintf_r(impure_ptr, ...) _vfprintf_r does the basic work. When the fmt string has a %f or other floating point specifier, it calls cvt(data, ...) to do the actual formatting. data is simply impure_ptr. cvt sets 'char *digits' to _ldtoa_r(data, ....) [again, data is our impure_ptr.) _ldtoa_r first off , enforces a limit on ndigits of 42 on cygwin (see ldtoa.c, #define NDEC for the algorithm). So 10000 is right out. However, this is the problem: cvt doesn't know that _ldtoa_r overrode ndigits to a "mere" 42. So, in this code (part of cvt()): 1168 digits = _ldtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve); 1169 #endif /* !_NO_LONGDBL */ 1170 1171 if ((ch != 'g' && ch != 'G') || flags & ALT) 1172 bp = digits + ndigits; we set bp to something WAY past the end of digits. Since rve points to the actual end of digits (where the '\0' is)... 1173 if (ch == 'f') { 1174 if (*digits == '0' && value) 1175 *decpt = -ndigits + 1; 1176 bp += *decpt; 1177 } 1178 if (value == 0) 1179 rve = bp; 1180 while (rve < bp) 1181 *rve++ = '0'; and then try to put 0's into digits[43...10000] in the while loop (lines 1180 and 1181). But, there were only 24 + (2^3-1)*4 == 52 bytes allocated for digits. I'm not sure what the correct fix is...should ndigits be passed by reference to _ldtoa_r, so that cvt "knows" that it got changed? (Ditto pass-by-reference to cvt so that vfprintf_r knows about the override as well). This changes the signature of these two (admittedly internal) routines, but I'm not sure of the "ripple effects" such a change might cause. Or is this a case of "doctor, it hurts when I do this?" "Don't call printf with prec specifiers greater than 42, then." --Chuck -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/