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

Bug#1036606: libmpfr6: multiple bugs in GNU MPFR 4.2.0, patches available



Package: libmpfr6
Version: 4.2.0-1
Severity: important
Tags: upstream

There are multiple bugs, more or less important, in GNU MPFR 4.2.0.
Patches are available at
  https://www.mpfr.org/mpfr-4.2.0/#bugs

In particular:
* For the mpfr_ui_pow_ui function, infinite loop in case of overflow.
* The mpfr_rec_sqrt function may yield a stack overflow due to many
  small allocations in the stack, based on alloca(). This occurs on
  cases that are very hard to round. In practice, to build such cases,
  the precision of the input needs to be large enough (e.g. around
  100000 bits).
* MPFR can crash when a formatted output function is called with
  %.2147483648Rg in the format string (2147483648 = 2^31).

See attached files for simple testcases (but the patches provide
testcases for the testsuite).

-- System Information:
Debian Release: 12.0
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'testing-security'), (500, 'stable-updates'), (500, 'stable-security'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental')
merged-usr: no
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.0-9-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=POSIX, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libmpfr6 depends on:
ii  libc6     2.36-9
ii  libgmp10  2:6.2.1+dfsg1-1.1

libmpfr6 recommends no packages.

libmpfr6 suggests no packages.

-- no debconf information

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)
#include <limits.h>
#include <stdio.h>
#include <mpfr.h>

int main (void)
{
  mpfr_exp_t emax_max;
  mpfr_t x;

  emax_max = mpfr_get_emax_max ();

  if (mpfr_set_emax (emax_max))
    {
      fprintf (stderr, "ui_pow_ui-overflow error: mpfr_set_emax failed\n");
      return 1;
    }

  mpfr_init2 (x, 8);

  /* The purpose of this test is more to check that mpfr_ui_pow_ui
     terminates (without taking much memory) rather than checking
     the value of x. On 2023-02-13, the +Inf case was not handled
     in the Ziv iteration, yielding an infinite loop, affecting
     mpfr_log10 in particular. See
       commit 90de094f0d9c309daca707aa227470d810866616
  */
  mpfr_ui_pow_ui (x, 5, ULONG_MAX, MPFR_RNDN);
  if (emax_max <= ULONG_MAX  /* true with default _MPFR_EXP_FORMAT */
      && ! mpfr_inf_p (x))
    {
      fprintf (stderr, "ui_pow_ui-overflow error");
      printf ("ui_pow_ui-overflow: expected +Inf, got ");
      mpfr_dump (x);
      return 1;
    }

  mpfr_clear (x);

  return 0;
}
#include <stdio.h>
#include <mpfr.h>

int main (void)
{
  mpfr_t x, y;
  int inex;

  mpfr_init2 (x, 123456);
  mpfr_init2 (y, 4);
  mpfr_set_ui (y, 9, MPFR_RNDN);
  mpfr_ui_div (x, 1, y, MPFR_RNDN);
  inex = mpfr_rec_sqrt (y, x, MPFR_RNDN);
  /* Let's also check the result, though this is not the real purpose
     of this test (a stack overflow just makes the program crash).
     1/9 = 0.111000111000111000111000111000111000...E-3 and since the
     precision 123456 is divisible by 6, x > 1/9. Thus 1/sqrt(x) < 3. */
  if (mpfr_nan_p (y) || mpfr_cmp_ui (y, 3) != 0 || inex <= 0)
    {
      printf ("mpfr_rec_sqrt error: expected 3 with inex > 0, got ");
      mpfr_out_str (stdout, 10, 0, y, MPFR_RNDN);
      printf (" with inex=%d\n", inex);
      return 1;
    }
  mpfr_clear (x);
  mpfr_clear (y);

  return 0;
}
#include <stdio.h>
#include <mpfr.h>

int main (void)
{
  mpfr_t x;
  char buf1[3] = "xxx", buf2[3] = "xxx";
  int r;

  mpfr_init2 (x, 128);
  mpfr_set_ui (x, 1, MPFR_RNDN);

  r = mpfr_snprintf (NULL, 0, "%.2147483648Rg\n", x);
  if (r != 2 && r >= 0)
    return 1;

  r = mpfr_snprintf (buf1, sizeof(buf1), "%.2147483648Rg\n", x);
  if (r != 2 && r >= 0)
    return 2;
  if (r >= 0 && (buf1[0] != '1' || buf1[1] != '\n' || buf1[2] != 0))
    return 3;

  r = mpfr_sprintf (buf2, "%.2147483648Rg\n", x);
  if (r != 2 && r >= 0)
    return 4;
  if (r >= 0 && (buf2[0] != '1' || buf2[1] != '\n' || buf2[2] != 0))
    return 5;

  mpfr_clear (x);
  return 0;
}

Reply to: