Subject: bin/13943: /bin/sh: Arithmetic Expansion possibly overflow (a hotbed of Sept. 9 date problem)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <h-suzuki@iij.ad.jp>
List: netbsd-bugs
Date: 09/13/2001 17:57:00
>Number: 13943
>Category: bin
>Synopsis: /bin/sh: Arithmetic Expansion possibly overflow (a hotbed of Sept. 9 date problem)
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Sep 13 01:58:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: SUZUKI Hideaki
>Release: NetBSD 1.5.1
>Organization:
>Environment:
System: NetBSD lepracaun 1.5.1 NetBSD 1.5.1 (LEPRACAUN) #2: Fri Jul 13 22:05:16 JST 2001 root@lepracaun.iij.ad.jp:/usr/src/sys/arch/i386/compile/LEPRACAUN i386
>Description:
The following sample script executes successfully when $today has a
value under 1,000,000,000. However, if $today has 1,000,000,000 or
more, the script returns incorrect result.
sample script:
----- cut here -----
#!/bin/sh
today=$(date +"%s")
echo $today
# if use $((expression))
yesterday=$((${today} - 86400))
echo $yesterday
# if use $(expr expression)
yesterdayoncemore=$(expr ${today} - 86400)
echo $yesterdayoncemore
# eof
----- cut here -----
The reason is in NetBSD/src/bin/sh/expand.c:expari():
int result;
(snip)
result = arith(p+2);
fmtstr(p, 10, "%d", result);
I believe fmtstr() function must not round off 'result' on 10 digits.
because 'int' valiable ranges from -2,147,483,648 to 2,147,483,647.
>How-To-Repeat:
Run something like as follows:
----- cut here -----
#!/bin/sh
today=$(date +"%s")
today2=$(date -r $today)
echo 'today:'
echo 'unixtime =' $today
echo $today2
echo
# if use $((expression))
#
yesterday=$((${today} - 86400))
yesterday2=$(date -r $yesterday)
echo 'yesterday:'
echo 'unixtime =' $yesterday
echo $yesterday2
echo
# if use $(expr expression)
#
yesterdayoncemore=$(expr ${today} - 86400)
yesterdayoncemore2=$(date -r $yesterdayoncemore)
echo 'yesterdayoncemore:'
echo 'unixtime =' $yesterdayoncemore
echo $yesterdayoncemore2
# eof
----- cut here -----
>Fix:
*** /usr/src/bin/sh/expand.c.orig Wed Sep 12 19:38:03 2001
--- /usr/src/bin/sh/expand.c Wed Sep 12 19:38:25 2001
***************
*** 393,399 ****
if (quotes)
rmescapes(p+2);
result = arith(p+2);
! fmtstr(p, 10, "%d", result);
while (*p++)
;
--- 393,399 ----
if (quotes)
rmescapes(p+2);
result = arith(p+2);
! fmtstr(p, 12, "%d", result);
while (*p++)
;
>Release-Note:
>Audit-Trail:
>Unformatted: