bug-gnu-emacs
[Top][All Lists]
Advanced

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

Re: simple elisp code crashes emacs


From: Tim Van Holder
Subject: Re: simple elisp code crashes emacs
Date: Wed, 25 Jul 2001 16:47:13 +0200

Chris Hecker wrote:
> 
> If you eval the following elisp code in a buffer with eval-last-sexp
> (once after the defun, then after the call), emacs 20.7 crashes on NT
> and hangs on Win98.  The crash appears to be in malloc.
> 
> (defun inv-newt (N S)
>   (let ((i 0) (iter 10)
>         (x N) xp)
>     (while (< i iter)
>       (setq xp (- (* 2.0 x) (* N x x)))
>       (insert (format "%f\n" xp))
>       (setq x xp)
>       (setq i (+ 1 i)))))
> 
> (inv-newt 2.0 2.0)

This happens on Linux as well, both in 20.7 and
21.0.103.1 (hence the CC: to pretest-bug).

My good friend edebug-defun tells me that the format call
crashes at iteration 9 (-9e243).
If the format string is changed to %g, you get normal results:

-4
-40
-3280
-2.15234e+07
-9.2651e+14
-1.71684e+30
-5.89509e+60
-6.95042e+121
-9.66167e+243
-inf

So it would seem some sort of internal buffer gets overrun in
format.

[* D/L pretest 103 again, rebuild with -gstabs+3 *]

OK - the crash happens in vfprintf, which gets called from
sprintf.  Oddly enough, sprintf seems to get a buffer containing
the 'correct' string (-966.........) and a format of
"773255248349010853888.0000003255248349010853888.0000003255" (no
further args).

The sprintf in question is from line 3398 of editfns.c

3393                  this_format[format - this_format_start] = 0;
3394    
3395                  if (INTEGERP (args[n]))
3396                    sprintf (p, this_format, XINT (args[n]));
3397                  else
3398                    sprintf (p, this_format, XFLOAT_DATA (args[n]));
3399    

this_format is likely to be screwed, as this_format_start
points to "%f\n" (@0x84ea840), but format is a wild pointer
(@0x3233302f).

While all of this is odd, it's not the actual problem. Instead,
the problem seems to be that the format size is set to
'max (field_width, 200 + precision) + 4', which isn't enough here.
float.h tells me that doubles can have exponents up to 308, so I'd
suggest changing the 200 to 308 (or DBL_MAX_10_EXP).  If emacs ever
uses long doubles (not sure if it does right now), this would need to
be increased even further (LDBL_MAX_10_EXP is 4932 on Linux with gcc3).

Doing so makes the above work:

-4.000000
-40.000000
-3280.000000
-21523360.000000
-926510094425920.000000
-1716841910146256220586780917760.000000
-5895092288869291438761194559071946489667222517086309222187008.000000
-69504226188572364921547011656304209225226289558733065214710946391547087812609628902500916751570627366238340917042587107328.000000
-9661674916144457323616194324673615767817374260418117520671176698204510302104631519124851935729071631083362275978749167486411387668390833220371769050039213194226068472352611721122006181223563543815302856826467619321936783934773255248349010853888.000000
-inf

Diff for editfns (against pretest 103) follows
(note: presumably a check for float.h would have to be added to
configure):

--- editfns.c~  Thu Apr 26 14:35:31 2001
+++ editfns.c   Wed Jul 25 16:40:36 2001
@@ -33,6 +33,10 @@
 #include <unistd.h>
 #endif
 
+#if defined HAVE_FLOAT_H
+# include <float.h>
+#endif
+
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -3266,7 +3274,11 @@
            /* Note that we're using sprintf to print floats,
               so we have to take into account what that function
               prints.  */
-           thissize = 200 + precision;
+#ifdef DBL_MAX_10_EXP
+           thissize = DBL_MAX_10_EXP + precision;
+#else
+           thissize = 333 + precision;
+#endif
          }
        else
          {


-- 
Tim Van Holder - Anubex N.V.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
This message was posted using plain text. I do not endorse any
products or services that may be hyperlinked to this message.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]