From egilb@barney.ife.no  Mon Jun 10 10:39:08 2002
Return-Path: <egilb@barney.ife.no>
Received: from barney.ife.no (barney.ife.no [128.39.229.49])
	by hub.freebsd.org (Postfix) with ESMTP id 5107B37B405
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 10 Jun 2002 10:39:07 -0700 (PDT)
Received: from malurt (malurt.ife.no [128.39.229.54])
	by barney.ife.no (8.9.3/8.9.3) with ESMTP id TAA29862;
	Mon, 10 Jun 2002 19:39:03 +0200 (MET DST)
Received: by malurt ; Mon, 10 Jun 2002 19:39:03 +0200 (CEST)
Message-Id: <200206101739.g5AHd3472231@malurt>
Date: Mon, 10 Jun 2002 19:39:03 +0200 (CEST)
From: Egil Brendsdal <egilb@ife.no>
Reply-To: egilb@ife.no
To: FreeBSD-gnats-submit@freebsd.org
Cc: egilb@ife.no
Subject: /usr/bin/printf
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         39116
>Category:       bin
>Synopsis:       /usr/bin/printf
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jun 10 10:40:01 PDT 2002
>Closed-Date:    Fri Jul 22 06:57:23 GMT 2005
>Last-Modified:  Fri Jul 22 06:57:23 GMT 2005
>Originator:     Egil Brendsdal
>Release:        FreeBSD 4.4-RELEASE i386
>Organization:
>Environment:
System: FreeBSD malurt.ife.no 4.4-RELEASE FreeBSD 4.4-RELEASE #1: Thu Oct 18 11:11:12 CEST 2001 root@malurt.ife.no:/usr/src/sys/compile/MALURT i386


	
>Description:
	

1) printf fails on \45 and multiple %% in the format string.
2) Field width specified by * gives unpredictable result.


>How-To-Repeat:
	

/usr/bin/printf, 4.4-RELEASE:

  egilb@malurt 101 % ident /usr/bin/printf
  /usr/bin/printf:
       $FreeBSD: src/usr.bin/printf/printf.c,v 1.12.6.4 2001/03/04 08:55:53 kris Exp $

  egilb@malurt 102 % /usr/bin/printf '\45\n'
  printf: illegal format character 

  egilb@malurt 103 % /usr/bin/printf '%%%s\n' a b c
  %a
  printf: illegal format character %

  egilb@malurt 104 % /usr/bin/printf '%*i\n'
  8589934592



Current version of printf from CVS:

  egilb@malurt 101 % ident ./printf
  ./printf:
       $FreeBSD: src/usr.bin/printf/printf.c,v 1.21 2002/04/25 01:10:11 tjr Exp $

  egilb@malurt 102 % ./printf '\45\n'
  printf: illegal format character 

  egilb@malurt 103 % 
  egilb@malurt 103 % ./printf '%%%s\n' a b c
  %a
  printf: illegal format character %

  egilb@malurt 104 % ./printf '%*i\n'
  8589934592


>Fix:

	

The source code of an alternative implementation of printf is available upon request.
Using this program, the result of the reported tests are:
  
  egilb@malurt 101 % my_printf '\45\n'
  %

  egilb@malurt 102 % my_printf '%%%s\n' a b c
  %a
  %b
  %c

  egilb@malurt 103 % my_printf '%*i\n'
  0

In addition, the bug due to internal zero-termination of the
format string is solved:

  egilb@malurt 104 % my_printf '\2\1\0\1\2' | od -c
  0000000  002 001  \0 001 002                                            
  0000005
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->tjr 
Responsible-Changed-By: tjr 
Responsible-Changed-When: Wed Jun 19 01:08:46 PDT 2002 
Responsible-Changed-Why:  
I will fix these problems. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 
State-Changed-From-To: open->patched 
State-Changed-By: tjr 
State-Changed-When: Wed Jun 19 03:36:37 PDT 2002 
State-Changed-Why:  


http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: freebsd-gnats-submit@FreeBSD.org, tjr@FreeBSD.org
Cc: egilb@ife.no
Subject: Re: bin/39116: /usr/bin/printf
Date: Wed, 4 Feb 2004 17:23:37 +0000 (GMT)

 This PR has been sat in the "patched" state for 19 months now.
 The changes to src/usr.bin/printf/printf.c (revisions 1.22-1.25) should be
 MFC'd and this PR should be closed.
Responsible-Changed-From-To: tjr->freebsd-bugs 
Responsible-Changed-By: tjr 
Responsible-Changed-When: Sat Feb 14 23:43:57 PST 2004 
Responsible-Changed-Why:  
Unassign due to lack of time and interest. Perhaps someone else 
will pick this up. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 
Responsible-Changed-From-To: freebsd-bugs->eik 
Responsible-Changed-By: eik 
Responsible-Changed-When: Fri Jul 2 23:22:46 CEST 2004 
Responsible-Changed-Why:  
I'll take it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 
Responsible-Changed-From-To: eik->freebsd-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Jul 18 03:56:02 GMT 2005 
Responsible-Changed-Why:  
With bugmeister hat on, reassign from inactive committer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 

From: Hiroo Ono <hiroo@oikumene.gcd.org>
To: bug-followup@FreeBSD.org, egilb@ife.no
Cc:  
Subject: Re: bin/39116: /usr/bin/printf
Date: Tue, 19 Jul 2005 23:21:44 +0900

 This may be duplicated on freebsd-bugs. It seems that I should have
 sent it to bug-followup@FreeBSD.org, sorry.
 
 The fix for this PR is done in HEAD
 src/usr.bin/printf/printf.c rev.1.22 to 1.25
 I made a MFC patch for this, and tested on RELENG_4,
 FreeBSD 4.11-STABLE #26: Sat Jul  2 02:02:27 JST 2005.
 
 Tested with the three cases in this PR. The results are same as on
 FreeBSD 5.4R-p4.
 
 chrysanthe% ./printf '\45\n'
 %
 chrysanthe% ./printf '%%%s\n' a b c
 %a
 %b
 %c
 chrysanthe% ./printf '%*i\n'
 0
 
 Would somebody commit it to RELENG_4 and close this PR?
 
 PR:             39116
 Submitted by:   Egil Brendsdal <egilb@ife.no>
 1.25
 Fix duplicate % in %b format introduced in rev 1.22.
 1.24
 Let printf(1) tell the difference between zero width/precision and
 unspecified width/precision.
 1.23
 Allow format strings containing "%%" to be reused.
 1.22
 Allow `%' to be written out with an octal escape (\45 or \045).
 
 ----------
 --- printf.c.orig	2005-07-19 12:58:43.513437500 +0900
 +++ printf.c	2005-07-19 11:04:20.013437500 +0900
 @@ -73,12 +73,12 @@
  
  #define PF(f, func) do { \
  	char *b = NULL; \
 -	if (fieldwidth) \
 -		if (precision) \
 +	if (havewidth) \
 +		if (haveprec) \
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
  		else \
  			(void)asprintf(&b, f, fieldwidth, func); \
 -	else if (precision) \
 +	else if (haveprec) \
  		(void)asprintf(&b, f, precision, func); \
  	else \
  		(void)asprintf(&b, f, func); \
 @@ -89,7 +89,7 @@
  } while (0)
  
  static int	 asciicode(void);
 -static int	 escape(char *);
 +static int	 escape(char *, int);
  static int	 getchr(void);
  static int	 getdouble(double *);
  static int	 getint(int *);
 @@ -111,7 +111,7 @@
  	char *argv[];
  {
  	static const char *skip1, *skip2;
 -	int ch, chopped, end, fieldwidth, precision, rval;
 +	int ch, chopped, end, fieldwidth, haveprec, havewidth, precision, rval;
  	char convch, nextch, *format, *fmt, *start;
  
  #ifndef BUILTIN
 @@ -143,7 +143,7 @@
  	skip1 = "#-+ 0";
  	skip2 = "0123456789";
  
 -	chopped = escape(fmt = format = *argv);	/* backslash interpretation */
 +	chopped = escape(fmt = format = *argv, 1);/* backslash interpretation */
  	rval = 0;
  	gargv = ++argv;
  	for (;;) {
 @@ -173,8 +173,8 @@
  			if (*fmt == '%') {
  				if (*++fmt != '%')
  					break;
 -				*fmt++ = '\0';
 -				(void)printf("%s", start);
 +				(void)printf("%.*s", (int)(fmt - start), start);
 +				fmt++;
  				goto next;
  			}
  		}
 @@ -184,9 +184,10 @@
  		if (*fmt == '*') {
  			if (getint(&fieldwidth))
  				return (1);
 +			havewidth = 1;
  			++fmt;
  		} else {
 -			fieldwidth = 0;
 +			havewidth = 0;
  
  			/* skip to possible '.', get following precision */
  			for (; strchr(skip2, *fmt); ++fmt);
 @@ -197,15 +198,16 @@
  			if (*fmt == '*') {
  				if (getint(&precision))
  					return (1);
 +				haveprec = 1;
  				++fmt;
  			} else {
 -				precision = 0;
 +				haveprec = 0;
  
  				/* skip to conversion char */
  				for (; strchr(skip2, *fmt); ++fmt);
  			}
  		} else
 -			precision = 0;
 +			haveprec = 0;
  		if (!*fmt) {
  			warnx1("missing format character", NULL, NULL);
  			return (1);
 @@ -228,7 +230,7 @@
  				warnx2("%s", strerror(ENOMEM), NULL);
  				return (1);
  			}
 -			getout = escape(p);
 +			getout = escape(p, 0);
  			*(fmt - 1) = 's';
  			PF(start, p);
  			*(fmt - 1) = 'b';
 @@ -323,8 +325,9 @@
  }
  
  static int
 -escape(fmt)
 +escape(fmt, percent)
  	register char *fmt;
 +	int percent;
  {
  	register char *store;
  	register int value, c;
 @@ -376,7 +379,11 @@
  				value += *fmt - '0';
  			}
  			--fmt;
 -			*store = value;
 +			if (percent && value == '%') {
 +				*store++ = '%';
 +				*store = '%';
 +			} else
 +				*store = value;
  			break;
  		default:
  			*store = *fmt;
 ----------
State-Changed-From-To: patched->closed 
State-Changed-By: linimon 
State-Changed-When: Fri Jul 22 06:56:42 GMT 2005 
State-Changed-Why:  
Fixed in 5.X; unless someone wants to merge it back to 4.X after all 
this time, the submitter suggests it should just be closed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=39116 
>Unformatted:
