bug in gmp_fprintf?

Torbjörn Granlund tg at gmplib.org
Sun Nov 29 19:57:17 UTC 2015


Our printf/scanf code is sloppily typed, and fixing that is more than a
few hours of work.  Changing sizes to size_t will not work in many cases
since the code relies on signedness.  I supppose ptrdiff_t might be
useful, but for now I change things to simply use 'long'.

The code needs a deeper cleanup.  At a minimum, the variable should be
more clearly named, and then used for its intended purpose.  And they
need to be carefully typed.

Plain stadio printf defines "precision" as an int; this might inadequate
for GMP.  Not sure how it works now or how we should actually handle it.

Please try the following patch.  I have only fixed things that caused
problems triggered by your test case, and things dependent on the
variables thus type changed.

If you could check the behaviour of rationals (huge numerator, huge
denominator, huge both) and huge-precision floats, that would be
helpful.

diff -Nrc2 gmp-main.bb072477386f/gmp-impl.h gmp-main/gmp-impl.h
*** gmp-main.bb072477386f/gmp-impl.h	Sun Nov 29 20:37:24 2015
--- gmp-main/gmp-impl.h	Sun Nov 29 20:37:25 2015
***************
*** 4408,4417 ****
    char        fill;          /* character */
    int         justify;       /* choices above */
!   int         prec;          /* prec field, or -1 for all digits */
    int         showbase;      /* choices above */
    int         showpoint;     /* if radix point always shown */
    int         showtrailing;  /* if trailing zeros wanted */
    char        sign;          /* '+', ' ', or '\0' */
!   int         width;         /* width field */
  };
  
--- 4408,4417 ----
    char        fill;          /* character */
    int         justify;       /* choices above */
!   long        prec;          /* prec field, or -1 for all digits */
    int         showbase;      /* choices above */
    int         showpoint;     /* if radix point always shown */
    int         showtrailing;  /* if trailing zeros wanted */
    char        sign;          /* '+', ' ', or '\0' */
!   long        width;         /* width field */
  };
  
diff -Nrc2 gmp-main.bb072477386f/printf/doprnt.c gmp-main/printf/doprnt.c
*** gmp-main.bb072477386f/printf/doprnt.c	Sun Nov 29 20:37:24 2015
--- gmp-main/printf/doprnt.c	Sun Nov 29 20:37:25 2015
***************
*** 164,168 ****
    char     *fmt, *alloc_fmt, *last_fmt, *this_fmt, *gmp_str;
    int      retval = 0;
!   int      type, fchar, *value, seen_precision;
    struct doprnt_params_t param;
  
--- 164,169 ----
    char     *fmt, *alloc_fmt, *last_fmt, *this_fmt, *gmp_str;
    int      retval = 0;
!   int      type, fchar, seen_precision;
!   long     *value;
    struct doprnt_params_t param;
  
***************
*** 588,592 ****
  	    /* process all digits to form a value */
  	    {
! 	      int  n = 0;
  	      do {
  		n = n * 10 + (fchar-'0');
--- 589,593 ----
  	    /* process all digits to form a value */
  	    {
! 	      long  n = 0;
  	      do {
  		n = n * 10 + (fchar-'0');
diff -Nrc2 gmp-main.bb072477386f/printf/doprnti.c gmp-main/printf/doprnti.c
*** gmp-main.bb072477386f/printf/doprnti.c	Sun Nov 29 20:37:24 2015
--- gmp-main/printf/doprnti.c	Sun Nov 29 20:37:25 2015
***************
*** 5,9 ****
     FUTURE GNU MP RELEASES.
  
! Copyright 2001 Free Software Foundation, Inc.
  
  This file is part of the GNU MP Library.
--- 5,9 ----
     FUTURE GNU MP RELEASES.
  
! Copyright 2001, 2015 Free Software Foundation, Inc.
  
  This file is part of the GNU MP Library.
***************
*** 49,53 ****
  {
    int         retval = 0;
!   int         slen, justlen, showbaselen, sign, signlen, slashlen, zeros;
    int         justify, den_showbaselen;
    const char  *slash, *showbase;
--- 49,54 ----
  {
    int         retval = 0;
!   long        slen, justlen, zeros, slashlen;
!   int         showbaselen, sign, signlen;
    int         justify, den_showbaselen;
    const char  *slash, *showbase;
diff -Nrc2 gmp-main.bb072477386f/scanf/doscan.c gmp-main/scanf/doscan.c
*** gmp-main.bb072477386f/scanf/doscan.c	Sun Nov 29 20:37:24 2015
--- gmp-main/scanf/doscan.c	Sun Nov 29 20:37:25 2015
***************
*** 191,195 ****
    int	ignore;
    char	type;
!   int	width;
  };
  
--- 191,195 ----
    int	ignore;
    char	type;
!   long	width;
  };
  
***************
*** 223,228 ****
  	 const struct gmp_doscan_params_t *p, void *dst)
  {
!   int	  chars, c, base, first, width, seen_point, seen_digit, hexfloat;
!   size_t  s_upto, s_alloc, hexexp;
    char	  *s;
    int	  invalid = 0;
--- 223,228 ----
  	 const struct gmp_doscan_params_t *p, void *dst)
  {
!   int	  c, base, first, seen_point, seen_digit, hexfloat;
!   size_t  chars, s_upto, width, s_alloc, hexexp;
    char	  *s;
    int	  invalid = 0;
***************
*** 239,243 ****
    first = 1;
    seen_point = 0;
!   width = (p->width == 0 ? INT_MAX-1 : p->width);
    base = p->base;
    s_alloc = S_ALLOC_STEP;
--- 239,243 ----
    first = 1;
    seen_point = 0;
!   width = (p->width == 0 ? LONG_MAX-1 : p->width);
    base = p->base;
    s_alloc = S_ALLOC_STEP;
***************
*** 475,482 ****
    const char  *fmt, *this_fmt, *end_fmt;
    size_t      orig_fmt_len, alloc_fmt_size, len;
-   int	      new_fields, new_chars;
    char	      fchar;
!   int	      fields = 0;
!   int	      chars = 0;
  
    TRACE (printf ("__gmp_doscan \"%s\"\n", orig_fmt);
--- 475,481 ----
    const char  *fmt, *this_fmt, *end_fmt;
    size_t      orig_fmt_len, alloc_fmt_size, len;
    char	      fchar;
!   int	      new_fields, fields = 0;
!   long	      new_chars, chars = 0;
  
    TRACE (printf ("__gmp_doscan \"%s\"\n", orig_fmt);

  

-- 
Torbjörn
Please encrypt, key id 0xC8601622


More information about the gmp-bugs mailing list