From jaakko@saunalahti.fi  Fri Apr 11 14:42:02 2008
Return-Path: <jaakko@saunalahti.fi>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id B9D231065672
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2008 14:42:02 +0000 (UTC)
	(envelope-from jaakko@saunalahti.fi)
Received: from gw01.mail.saunalahti.fi (gw01.mail.saunalahti.fi [195.197.172.115])
	by mx1.freebsd.org (Postfix) with ESMTP id F3BC08FC1B
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2008 14:42:01 +0000 (UTC)
	(envelope-from jaakko@saunalahti.fi)
Received: from ws64.jh.dy.fi (GMKDCCCII.dsl.saunalahti.fi [85.76.249.203])
	by gw01.mail.saunalahti.fi (Postfix) with ESMTP id C0D3A151B3D
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2008 17:41:59 +0300 (EEST)
Received: from ws64.jh.dy.fi (localhost [127.0.0.1])
	by ws64.jh.dy.fi (8.14.2/8.14.2) with ESMTP id m3BEfxS8006721
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 11 Apr 2008 17:41:59 +0300 (EEST)
	(envelope-from jaakko@ws64.jh.dy.fi)
Received: (from jaakko@localhost)
	by ws64.jh.dy.fi (8.14.2/8.14.2/Submit) id m3BEfxYL006720;
	Fri, 11 Apr 2008 17:41:59 +0300 (EEST)
	(envelope-from jaakko)
Message-Id: <200804111441.m3BEfxYL006720@ws64.jh.dy.fi>
Date: Fri, 11 Apr 2008 17:41:59 +0300 (EEST)
From: Jaakko Heinonen <jh@saunalahti.fi>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] sh(1) long arithmetics broken on certain architectures
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         122659
>Category:       bin
>Synopsis:       [patch] sh(1) long arithmetics broken on certain architectures
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    stefanf
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 11 14:50:00 UTC 2008
>Closed-Date:    Sun May 16 10:11:46 UTC 2010
>Last-Modified:  Sun May 16 10:11:46 UTC 2010
>Originator:     Jaakko Heinonen
>Release:        FreeBSD 7.0-RELEASE amd64
>Organization:
>Environment:
System: FreeBSD x 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Sun Feb 24 10:35:36 UTC 2008 root@driscoll.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64

>Description:
This PR partially supersedes bin/51171.

In src/bin/sh/shell.h there's a following comment:

/*
 * Type of used arithmetics. SUSv3 requires us to have at least signed long.
 */

However in sh(1) code int type is used in several places for arithmetics
which prevents long arithmetics to work on architectures where
sizeof(int) != sizeof(long).

>How-To-Repeat:
$ sh -c 'uname -m; echo $((2147483647 + 1))'
amd64
-2147483648
>Fix:
I have attached two patches here. The first one converts places still using
int instead of arith_t to use arith_t. It also converts hardcoded format
strings to ARITH_FORMAT_STR and removes the hardcoded limitation of 10
characters for numbers.

The second patch which must be applied on top of the first one converts
arith_t from long to intmax_t. This patch is not strictly needed to comply
with SUS but it extends 32 bit arithmetics to 64 bits for example on i386.

--- sh-long-arith.diff begins here ---
Index: arith.h
===================================================================
RCS file: /home/ncvs/src/bin/sh/arith.h,v
retrieving revision 1.11
diff -p -u -r1.11 arith.h
--- arith.h	13 Aug 2005 07:59:46 -0000	1.11
+++ arith.h	9 Apr 2008 12:19:06 -0000
@@ -30,8 +30,10 @@
  * $FreeBSD: src/bin/sh/arith.h,v 1.11 2005/08/13 07:59:46 stefanf Exp $
  */
 
+#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
+
 extern char *arith_buf, *arith_startbuf;
 
-int arith(char *);
+arith_t arith(char *);
 void arith_lex_reset(void);
 int expcmd(int, char **);
Index: arith.y
===================================================================
RCS file: /home/ncvs/src/bin/sh/arith.y,v
retrieving revision 1.21
diff -p -u -r1.21 arith.y
--- arith.y	13 Aug 2005 07:59:46 -0000	1.21
+++ arith.y	9 Apr 2008 12:19:06 -0000
@@ -43,8 +43,8 @@ __FBSDID("$FreeBSD: src/bin/sh/arith.y,v
 #include <limits.h>
 #include <stdio.h>
 
-#include "arith.h"
 #include "shell.h"
+#include "arith.h"
 #include "var.h"
 %}
 %union {
@@ -75,7 +75,10 @@ __FBSDID("$FreeBSD: src/bin/sh/arith.y,v
 
 exp:
 	expr
-		{ return ($1); }
+		{
+		*(YYPARSE_PARAM) = ($1);
+		return (0);
+		}
 	;
 
 expr:
@@ -259,12 +262,13 @@ expr:
 #include "output.h"
 #include "memalloc.h"
 
-#define lstrlen(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
+#define YYPARSE_PARAM_TYPE arith_t *
+#define YYPARSE_PARAM result
 
 char *arith_buf, *arith_startbuf;
 
 int yylex(void);
-int yyparse(void);
+int yyparse(YYPARSE_PARAM_TYPE);
 
 static int
 arith_assign(char *name, arith_t value)
@@ -279,15 +283,15 @@ arith_assign(char *name, arith_t value)
 	return ret;
 }
 
-int
+arith_t
 arith(char *s)
 {
-	long result;
+	arith_t result;
 
 	arith_buf = arith_startbuf = s;
 
 	INTOFF;
-	result = yyparse();
+	yyparse(&result);
 	arith_lex_reset();	/* Reprime lex. */
 	INTON;
 
@@ -313,7 +317,7 @@ expcmd(int argc, char **argv)
 	char *p;
 	char *concat;
 	char **ap;
-	long i;
+	arith_t i;
 
 	if (argc > 1) {
 		p = argv[1];
@@ -338,8 +342,8 @@ expcmd(int argc, char **argv)
 
 	i = arith(p);
 
-	out1fmt("%ld\n", i);
-	return !i;
+	out1fmt(ARITH_FORMAT_STR "\n", i);
+	return ((int)!i);
 }
 
 /*************************/
Index: arith_lex.l
===================================================================
RCS file: /home/ncvs/src/bin/sh/arith_lex.l,v
retrieving revision 1.24
diff -p -u -r1.24 arith_lex.l
--- arith_lex.l	13 Aug 2005 07:59:46 -0000	1.24
+++ arith_lex.l	9 Apr 2008 12:19:06 -0000
@@ -42,8 +42,8 @@ __FBSDID("$FreeBSD: src/bin/sh/arith_lex
 
 #include <string.h>
 
-#include "arith.h"
 #include "shell.h"
+#include "arith.h"
 #include "y.tab.h"
 #include "error.h"
 #include "memalloc.h"
Index: expand.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/expand.c,v
retrieving revision 1.51
diff -p -u -r1.51 expand.c
--- expand.c	7 Nov 2006 22:46:13 -0000	1.51
+++ expand.c	9 Apr 2008 12:19:06 -0000
@@ -356,7 +356,7 @@ void
 expari(int flag)
 {
 	char *p, *start;
-	int result;
+	arith_t result;
 	int begoff;
 	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
 	int quoted;
@@ -372,10 +372,7 @@ expari(int flag)
 	 * have to rescan starting from the beginning since CTLESC
 	 * characters have to be processed left to right.
 	 */
-#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
-#error "integers with more than 10 digits are not supported"
-#endif
-	CHECKSTRSPACE(12 - 2, expdest);
+	CHECKSTRSPACE(lstrlen(result) - 2, expdest);
 	USTPUTC('\0', expdest);
 	start = stackblock();
 	p = expdest - 2;
@@ -397,7 +394,7 @@ expari(int flag)
 	if (quotes)
 		rmescapes(p+2);
 	result = arith(p+2);
-	fmtstr(p, 12, "%d", result);
+	fmtstr(p, lstrlen(result), ARITH_FORMAT_STR, result);
 	while (*p++)
 		;
 	if (quoted == 0)
--- sh-long-arith.diff ends here ---

--- sh-arith-intmax_t.diff begins here ---
--- sh/shell.h	2008-04-09 13:10:06.000000000 +0300
+++ sh/shell.h	2008-04-09 13:16:03.000000000 +0300
@@ -33,6 +33,8 @@
  * $FreeBSD: src/bin/sh/shell.h,v 1.17 2004/04/06 20:06:51 markm Exp $
  */
 
+#include <inttypes.h>
+
 /*
  * The follow should be set to reflect the type of system you have:
  *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
@@ -50,10 +52,10 @@
 /*
  * Type of used arithmetics. SUSv3 requires us to have at least signed long.
  */
-typedef long arith_t;
-#define	ARITH_FORMAT_STR  "%ld"
-#define	atoarith_t(arg)  strtol(arg, NULL, 0)
-#define	strtoarith_t(nptr, endptr, base)  strtol(nptr, endptr, base)
+typedef intmax_t arith_t;
+#define	ARITH_FORMAT_STR  "%" PRIdMAX
+#define	atoarith_t(arg)  strtoimax(arg, NULL, 0)
+#define	strtoarith_t(nptr, endptr, base)  strtoimax(nptr, endptr, base)
 
 typedef void *pointer;
 #define STATIC  static
--- sh-arith-intmax_t.diff ends here ---


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->stefanf 
Responsible-Changed-By: stefanf 
Responsible-Changed-When: Sat Apr 19 15:27:40 UTC 2008 
Responsible-Changed-Why:  
I will handle this. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/122659: commit references a PR
Date: Sun, 27 Apr 2008 20:25:52 +0000 (UTC)

 stefanf     2008-04-27 20:25:43 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     bin/sh               arith.h arith.y expand.c shell.h 
   Log:
   - Fix bugs where the value of arithmetic expansion$((...)) was trucated
     to type int.
   - Change the type used for arithmetic expansion to intmax_t (ie. 64 bit on all
     currently supported FreeBSD architectures).  SUSv3 requires at least type
     long but allows for larger types.  Other shells (eg. bash, zsh, NetBSD's sh)
     do that too.
   
   PR:             122659
   Submitted by:   Jaakko Heinonen (minor modifications by me)
   
   Revision  Changes    Path
   1.9.8.2   +5 -1      src/bin/sh/arith.h
   1.19.8.2  +13 -9     src/bin/sh/arith.y
   1.47.2.4  +3 -6      src/bin/sh/expand.c
   1.17.8.1  +11 -4     src/bin/sh/shell.h
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/122659: commit references a PR
Date: Sun, 27 Apr 2008 20:46:51 +0000 (UTC)

 stefanf     2008-04-27 20:46:45 UTC
 
   FreeBSD src repository
 
   Modified files:
     bin/sh               arith.h arith.y shell.h 
   Log:
   - Fix bugs where the value of arithmetic expansion$((...)) was trucated
     to type int.
   - Change the type used for arithmetic expansion to intmax_t (ie. 64 bit on all
     currently supported FreeBSD architectures).  SUSv3 requires at least type
     long but allows for larger types.  Other shells (eg. bash, zsh, NetBSD's sh)
     do that too.
   
   PR:             122659
   Submitted by:   Jaakko Heinonen (minor modifications by me)
   
   Revision  Changes    Path
   1.12      +5 -1      src/bin/sh/arith.h
   1.22      +13 -9     src/bin/sh/arith.y
   1.18      +11 -4     src/bin/sh/shell.h
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: stefanf 
State-Changed-When: Mon Apr 28 18:23:56 UTC 2008 
State-Changed-Why:  
Fixed in HEAD. 

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

From: Volker <volker@vwsoft.com>
To: bug-followup@FreeBSD.org, stefanf@freebsd.org
Cc: jh@saunalahti.fi
Subject: Re: bin/122659: [patch] sh(1) long arithmetics broken on certain
 architectures
Date: Sat, 10 May 2008 22:04:42 +0200

 Stefan,
 
 this has been committed to HEAD and RELENG_6 but not to RELENG_7. Can
 you please check?
 
 Volker

From: Stefan Farfeleder <stefanf@FreeBSD.org>
To: Volker <volker@vwsoft.com>, bug-followup@FreeBSD.org
Cc: jh@saunalahti.fi
Subject: Re: bin/122659: [patch] sh(1) long arithmetics broken on certain
	architectures
Date: Sun, 11 May 2008 11:52:00 +0200

 On Sat, May 10, 2008 at 07:10:04PM +0000, Volker wrote:
 > The following reply was made to PR bin/122659; it has been noted by GNATS.
 > 
 > From: Volker <volker@vwsoft.com>
 > To: bug-followup@FreeBSD.org, stefanf@freebsd.org
 > Cc: jh@saunalahti.fi
 > Subject: Re: bin/122659: [patch] sh(1) long arithmetics broken on certain
 >  architectures
 > Date: Sat, 10 May 2008 22:04:42 +0200
 > 
 >  Stefan,
 >  
 >  this has been committed to HEAD and RELENG_6 but not to RELENG_7. Can
 >  you please check?
 
 The commit to RELENG_6 was an error and backed out.  I will merge this
 change to RELENG_{6,7} these days.
State-Changed-From-To: patched->closed 
State-Changed-By: stefanf 
State-Changed-When: Sun May 16 10:10:51 UTC 2010 
State-Changed-Why:  
Already merged back into 7 and 8. 

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