Subject: bug#32476: closed (Re: 27.0.50; Assertion failure for dot-terminated large int)

From: [email-masked] (GNU bug Tracking System)
Date: Tue, 21 Aug 2018 22:53:02 +0000

Your bug report

#32476: 27.0.50; Assertion failure for dot-terminated large int

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
32476: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=32476
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: 27.0.50; Assertion failure for dot-terminated large int
From: Paul Eggert <[email-masked]>
To: Stefan Monnier <[email-masked]>
Cc: [email-masked]
Date: Tue, 21 Aug 2018 15:52:38 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Thanks for reporting that; I installed the attached to fix it.

>From f8069952abf147d090032ad6b941a728cad2c496 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Tue, 21 Aug 2018 15:49:01 -0700
Subject: [PATCH] Fix assertion failure when reading 'BIGNUM.'

Problem reported by Stefan Monnier (Bug#32476).
* src/lread.c (string_to_number): Don't pass leading "+"
or trailing "." or junk to make_bignum_str.
* test/src/lread-tests.el (lread-string-to-number-trailing-dot):
New test.
---
 src/lread.c             | 21 ++++++++++++++++-----
 test/src/lread-tests.el |  9 +++++++++
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/src/lread.c b/src/lread.c
index df2fe58120..5e1bd419fa 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -3710,8 +3710,9 @@ string_to_number (char const *string, int base, int flags)
      IEEE floating point hosts, and works around a formerly-common bug where
      atof ("-0.0") drops the sign.  */
   bool negative = *cp == '-';
+  bool positive = *cp == '+';
 
-  bool signedp = negative || *cp == '+';
+  bool signedp = negative | positive;
   cp += signedp;
 
   enum { INTOVERFLOW = 1, LEAD_INT = 2, DOT_CHAR = 4, TRAIL_INT = 8,
@@ -3732,6 +3733,7 @@ string_to_number (char const *string, int base, int flags)
 	  n += digit;
 	}
     }
+  char const *after_digits = cp;
   if (*cp == '.')
     {
       state |= DOT_CHAR;
@@ -3807,10 +3809,19 @@ string_to_number (char const *string, int base, int flags)
 	  return make_fixnum (negative ? -signed_n : signed_n);
 	}
 
-      /* Skip a leading "+".  */
-      if (signedp && !negative)
-	++string;
-      return make_bignum_str (string, base);
+      /* Trim any leading "+" and trailing nondigits, then convert to
+	 bignum.  */
+      string += positive;
+      if (!*after_digits)
+	return make_bignum_str (string, base);
+      ptrdiff_t trimmed_len = after_digits - string;
+      USE_SAFE_ALLOCA;
+      char *trimmed = SAFE_ALLOCA (trimmed_len + 1);
+      memcpy (trimmed, string, trimmed_len);
+      trimmed[trimmed_len] = '\0';
+      Lisp_Object result = make_bignum_str (trimmed, base);
+      SAFE_FREE ();
+      return result;
     }
 
   /* Either the number uses float syntax, or it does not fit into a fixnum.
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index 17381340c7..f19d98320a 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -209,4 +209,13 @@ lread-tests--last-message
   (should-error
    (let ((load-force-doc-strings t)) (read "#[0 \"\"]"))))
 
+(ert-deftest lread-string-to-number-trailing-dot ()
+  (dolist (n (list (* most-negative-fixnum most-negative-fixnum)
+                   (1- most-negative-fixnum) most-negative-fixnum
+                   (1+ most-negative-fixnum) -1 0 1
+                   (1- most-positive-fixnum) most-positive-fixnum
+                   (1+ most-positive-fixnum)
+                   (* most-positive-fixnum most-positive-fixnum)))
+    (should (= n (string-to-number (format "%d." n))))))
+
 ;;; lread-tests.el ends here
-- 
2.17.1

Subject: 27.0.50; Assertion failure for dot-terminated large int
From: Stefan Monnier <[email-masked]>
To: [email-masked]
Cc: Chris Feng <[email-masked]>
Date: Sun, 19 Aug 2018 18:50:57 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

Package: Emacs
Version: 27.0.50

With the nw bignum code in Emacs master, reading a large integer with
trailing dot triggers an assertion failure:

    M-: 4294967295. RET

for me triggers the problem (seen in elpa/packages/xelb/xcb-types.el).
I suspect on a 64bit host you'll need:

    M-: 18446744073709551615. RET

to trigger the same bug (the integer needs to be large enough not to
fit in a Lisp fixnum but small enough to fit in a uintmax_t).

The assertion that fails is the `eassert (check == 0)`
in alloc.c:make_bignum_str.

BTW, I was surprised to discover that until now "42." was read as the
*integer* of value 42 rather than the float of that value.  I guess
we're stuck with this behavior but I find it odd.

        Stefan

In GNU Emacs 27.0.50 (build 1, x86_64-unknown-linux-gnu, GTK+ Version 3.22.30)
 of 2018-08-19 built on alfajor
Repository revision: 14acf8634c0b359fbbd3234dff65b40d9a12f26d
Windowing system distributor 'The X.Org Foundation', version 11.0.11906000
System Description: Debian GNU/Linux buster/sid

Recent messages:
Required package ‘helm-1.0’ is unavailable
Unable to activate package ‘ebdb-i18n-chn’.
Required package ‘pyim-1.6.0’ is unavailable
Loading /home/monnier/src/elisp/ProofGeneral/generic/proof-site.el (source)...done
Loading /home/monnier/etc/emacs/X11.el (source)...done
Loading /home/monnier/etc/emacs/custom.el (source)...done
Ispell-kill: nil american
Starting new Ispell process /usr/bin/aspell with american dictionary...
Warning: hide-sublevels is obsolete!
For information about GNU Emacs and the GNU system, type C-h C-a.

Configured using:
 'configure -C --enable-checking --with-modules --enable-check-lisp-object-type
 'CFLAGS=-Wall -g3 -Og -Wno-pointer-sign'
 PKG_CONFIG_PATH=/home/monnier/lib/pkgconfig'

Configured features:
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GSETTINGS NOTIFY
GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS
GTK3 X11 MODULES THREADS LCMS2 GMP

Important settings:
  value of $LANG: fr_CH.UTF-8
  locale-coding-system: utf-8-unix

Major mode: InactiveMinibuffer

Minor modes in effect:
  electric-pair-mode: t
  global-reveal-mode: t
  reveal-mode: t
  auto-insert-mode: t
  savehist-mode: t
  minibuffer-electric-default-mode: t
  global-compact-docstrings-mode: t
  url-handler-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  global-prettify-symbols-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
/home/monnier/src/emacs/elpa/packages/svg/svg hides /home/monnier/src/emacs/work/lisp/svg
/home/monnier/src/emacs/elpa/packages/ada-mode/ada-mode hides /home/monnier/src/emacs/work/lisp/progmodes/ada-mode
/home/monnier/src/emacs/elpa/packages/ada-mode/ada-stmt hides /home/monnier/src/emacs/work/lisp/progmodes/ada-stmt
/home/monnier/src/emacs/elpa/packages/ada-mode/ada-prj hides /home/monnier/src/emacs/work/lisp/progmodes/ada-prj
/home/monnier/src/emacs/elpa/packages/ada-mode/ada-xref hides /home/monnier/src/emacs/work/lisp/progmodes/ada-xref
/home/monnier/src/emacs/elpa/packages/hyperbole/set hides /home/monnier/src/emacs/work/lisp/emacs-lisp/set
/home/monnier/src/emacs/elpa/packages/landmark/landmark hides /home/monnier/src/emacs/work/lisp/obsolete/landmark
/home/monnier/src/emacs/elpa/packages/crisp/crisp hides /home/monnier/src/emacs/work/lisp/obsolete/crisp

Features:
(shadow sort mail-extr emacsbug message rmc puny dired dired-loaddefs
format-spec rfc822 mml mml-sec epa gnus-util rmail rmail-loaddefs
mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils
mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr
mail-utils server time-date flymake-proc flymake compile comint
ansi-color ring warnings noutline outline easy-mmode flyspell ispell
checkdoc thingatpt load-dir elec-pair reveal autoinsert proof-site
proof-autoloads cl pg-vars savehist minibuf-eldef disp-table
compact-docstrings kotl-autoloads advice info
realgud-recursive-autoloads url-auth finder-inf package let-alist
derived pcase cl-extra help-mode easymenu cl-seq inline url-handlers
url-parse auth-source eieio eieio-core cl-macs eieio-loaddefs
password-cache json map url-vars seq byte-opt gv bytecomp byte-compile
cconv epg epg-config subr-x cl-loaddefs cl-lib mule-util tooltip eldoc
electric uniquify ediff-hook vc-hooks lisp-float-type mwheel term/x-win
x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page menu-bar rfn-eshadow isearch timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan
thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian
slovak czech european ethiopic indian cyrillic chinese composite
charscript charprop case-table epa-hook jka-cmpr-hook help simple abbrev
obarray minibuffer cl-preloaded nadvice loaddefs button faces cus-face
macroexp files text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget hashtable-print-readable backquote threads
dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting move-toolbar gtk x-toolkit x multi-tty
make-network-process emacs)

Memory information:
((conses 8 176553 15999)
 (symbols 24 25413 1) (strings 16 53114 3586) (string-bytes 1 1719428)
 (vectors 12 22395)
 (vector-slots 4 633679 13932) (floats 8 74 43) (intervals 28 255 0)
 (buffers 536 14))