Subject: 31.0.50; Segfault on Windows 11 when using Easy Customization buffer

From: Amir Rajan <[email-masked]>
Date: Fri, 10 Jan 2025 13:39:34 -0600

In GNU Emacs 31.0.50 (build 1, x86_64-w64-mingw32) of 2025-01-10 built on
AMIRALIRAJA2ACF
Repository revision: 42a5ac3b513ff03c64c9609fc7e79c2b7932b2a4
Repository branch: master
System Description: M1 Mac Book Pro running Windows 11 VM using Parallels

Configured using:
 'configure --enable-checking --prefix=/c/emacs --without-dbus
 'CFLAGS=-ggdb3 -O0' LDFLAGS=-ggdb3'

Configured features:
ACL GIF GMP GNUTLS HARFBUZZ JPEG LCMS2 LIBXML2 MODULES NATIVE_COMP
NOTIFY W32NOTIFY PDUMPER PNG RSVG SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP XPM ZLIB

Important settings:
  value of $LC_CTYPE: en_US.UTF-8
  value of $LANG: ENU
  locale-coding-system: cp1252

Minimum repro:
  emacs -Q
  M-x customize-mode
  Type anything into search box
  Press Enter

Backtrace:
  addr2line -C -f -i -p -e ./src/emacs.exe < ./emacs_backtrace.txt
  ?? ??:0
  ?? ??:0
  ?? ??:0
  w32_backtrace at C:/other-projects/emacs/src/w32fns.c:11571
  emacs_abort at C:/other-projects/emacs/src/w32fns.c:11610
  terminate_due_to_signal at C:/other-projects/emacs/src/emacs.c:464
  handle_fatal_signal at C:/other-projects/emacs/src/sysdep.c:1799
  deliver_thread_signal at C:/other-projects/emacs/src/sysdep.c:1791
  deliver_fatal_thread_signal at C:/other-projects/emacs/src/sysdep.c:1811
  ?? ??:0
  ?? ??:0
  ?? ??:0
  ?? ??:0
  ?? ??:0
  rescale_for_division at C:/other-projects/emacs/src/floatfns.c:387
  rounding_driver at C:/other-projects/emacs/src/floatfns.c:442
  Ffloor at C:/other-projects/emacs/src/floatfns.c:536
  funcall_subr at C:/other-projects/emacs/src/eval.c:3152
  exec_byte_code at C:/other-projects/emacs/src/bytecode.c:813
  funcall_lambda at C:/other-projects/emacs/src/eval.c:3241
  funcall_general at C:/other-projects/emacs/src/eval.c:3033
  Ffuncall at C:/other-projects/emacs/src/eval.c:3082
  Fapply at C:/other-projects/emacs/src/eval.c:2754
  funcall_subr at C:/other-projects/emacs/src/eval.c:3173
  funcall_general at C:/other-projects/emacs/src/eval.c:3029
  Ffuncall at C:/other-projects/emacs/src/eval.c:3082
  ?? ??:0
  funcall_subr at C:/other-projects/emacs/src/eval.c:3150
  funcall_general at C:/other-projects/emacs/src/eval.c:3029
  Ffuncall at C:/other-projects/emacs/src/eval.c:3082
  timer_check_2 at C:/other-projects/emacs/src/keyboard.c:4804
  timer_check at C:/other-projects/emacs/src/keyboard.c:4869
  readable_events at C:/other-projects/emacs/src/keyboard.c:3601
  get_input_pending at C:/other-projects/emacs/src/keyboard.c:7872
  detect_input_pending_run_timers at
C:/other-projects/emacs/src/keyboard.c:11576
  wait_reading_process_output at C:/other-projects/emacs/src/process.c:5856
  sit_for at C:/other-projects/emacs/src/dispnew.c:6889
  read_char at C:/other-projects/emacs/src/keyboard.c:2925
  read_key_sequence at C:/other-projects/emacs/src/keyboard.c:10746
  command_loop_1 at C:/other-projects/emacs/src/keyboard.c:1424
  internal_condition_case at C:/other-projects/emacs/src/eval.c:1603
  command_loop_2 at C:/other-projects/emacs/src/keyboard.c:1163
  internal_catch at C:/other-projects/emacs/src/eval.c:1286
  command_loop at C:/other-projects/emacs/src/keyboard.c:1141
  recursive_edit_1 at C:/other-projects/emacs/src/keyboard.c:747
  Frecursive_edit at C:/other-projects/emacs/src/keyboard.c:830
  main at C:/other-projects/emacs/src/emacs.c:2635
  __tmainCRTStartup at C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:266
  mainCRTStartup at C:/M/B/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:185
  __start at C:/other-projects/emacs/src/w32proc.c:158
  ?? ??:0
  ?? ??:0
  ?? ??:0

Notes:
Updating the rounding_driver function in ./src/floatfns.c from Emacs 26
resolved the issue.

diff --git a/src/floatfns.c b/src/floatfns.c
index 4492815c765..26c2e15da05 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -400,48 +400,79 @@ rescale_for_division (Lisp_Object n, mpz_t *t, int
nscale, int dscale)

 /* the rounding functions  */

+static bool
+integer_value (Lisp_Object a)
+{
+  if (FLOATP (a))
+    {
+      double d = XFLOAT_DATA (a);
+      return d == floor (d) && isfinite (d);
+    }
+  return true;
+}
+
 static Lisp_Object
-rounding_driver (Lisp_Object n, Lisp_Object d,
+rounding_driver (Lisp_Object arg, Lisp_Object divisor,
  double (*double_round) (double),
  void (*int_divide) (mpz_t, mpz_t const, mpz_t const),
  EMACS_INT (*fixnum_divide) (EMACS_INT, EMACS_INT))
 {
-  CHECK_NUMBER (n);
+  CHECK_NUMBER (arg);

-  if (NILP (d))
-    return FLOATP (n) ? double_to_integer (double_round (XFLOAT_DATA (n)))
: n;
-
-  CHECK_NUMBER (d);
-
-  int dscale = 0;
-  if (FIXNUMP (d))
+  double d;
+  if (NILP (divisor))
     {
-      if (XFIXNUM (d) == 0)
- xsignal0 (Qarith_error);
-
-      /* Divide fixnum by fixnum specially, for speed.  */
-      if (FIXNUMP (n))
- return make_int (fixnum_divide (XFIXNUM (n), XFIXNUM (d)));
+      if (! FLOATP (arg))
+ return arg;
+      d = XFLOAT_DATA (arg);
     }
-  else if (FLOATP (d))
+  else
     {
-      if (XFLOAT_DATA (d) == 0)
- xsignal0 (Qarith_error);
-      dscale = double_integer_scale (XFLOAT_DATA (d));
-    }
+      CHECK_NUMBER (divisor);
+      if (integer_value (arg) && integer_value (divisor))
+ {
+  /* Divide as integers.  Converting to double might lose
+     info, even for fixnums; also see the FIXME below.  */

-  int nscale = FLOATP (n) ? double_integer_scale (XFLOAT_DATA (n)) : 0;
+  if (FLOATP (arg))
+    arg = double_to_integer (XFLOAT_DATA (arg));
+  if (FLOATP (divisor))
+    divisor = double_to_integer (XFLOAT_DATA (divisor));

-  /* If the numerator is finite and the denominator infinite, the
-     quotient is zero and there is no need to try the impossible task
-     of rescaling the denominator.  */
-  if (dscale == DBL_MANT_DIG - DBL_MIN_EXP + 1 && nscale < dscale)
-    return make_fixnum (0);
+  if (FIXNUMP (divisor))
+    {
+      if (XFIXNUM (divisor) == 0)
+ xsignal0 (Qarith_error);
+      if (FIXNUMP (arg))
+ return make_int (fixnum_divide (XFIXNUM (arg),
+ XFIXNUM (divisor)));
+    }
+  int_divide (mpz[0],
+      ,*bignum_integer (&mpz[0], arg),
+      ,*bignum_integer (&mpz[1], divisor));
+  return make_integer_mpz ();
+ }

-  int_divide (mpz[0],
-      *rescale_for_division (n, &mpz[0], nscale, dscale),
-      *rescale_for_division (d, &mpz[1], dscale, nscale));
-  return make_integer_mpz ();
+      double f1 = XFLOATINT (arg);
+      double f2 = XFLOATINT (divisor);
+      if (! IEEE_FLOATING_POINT && f2 == 0)
+ xsignal0 (Qarith_error);
+      /* FIXME: This division rounds, so the result is double-rounded.  */
+      d = f1 / f2;
+    }
+
+  /* Round, coarsely test for fixnum overflow before converting to
+     EMACS_INT (to avoid undefined C behavior), and then exactly test
+     for overflow after converting (as FIXNUM_OVERFLOW_P is inaccurate
+     on floats).  */
+  double dr = double_round (d);
+  if (fabs (dr) < 2 * (MOST_POSITIVE_FIXNUM + 1))
+    {
+      EMACS_INT ir = dr;
+      if (! FIXNUM_OVERFLOW_P (ir))
+ return make_fixnum (ir);
+    }
+  return double_to_integer (dr);
 }

 static EMACS_INT