bug-bash
[Top][All Lists]
Advanced

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

IFS boundary behaviour is not consistent passing arguments to a function


From: McCue, Glenn (SSC/SPC)
Subject: IFS boundary behaviour is not consistent passing arguments to a function for bash 4.3 or 4.4 .
Date: Tue, 3 Oct 2017 03:26:03 +0000

From: gmccue
To: address@hidden
Subject:  IFS boundary error - bash 4.3 or 4.4 function call

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.3 
-L/home/abuild/rpmbuild/BUILD/bash-4.3/../readline-6.3
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' 
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -fmessage-length=0 
-grecord-gcc-switches -fstack-protector -O2 -Wall -D_FORTIFY_SOURCE=2 
-funwind-tables -fasynchronous-unwind-tables -g  -D_GNU_SOURCE -DRECYCLES_PIDS 
-Wall -g -Wuninitialized -Wextra -Wno-unprototyped-calls -Wno-switch-enum 
-Wno-unused-variable -Wno-unused-parameter -Wno-parentheses -ftree-loop-linear 
-pipe -DBNC382214=0 -DIMPORT_FUNCTIONS_DEF=0 -fprofile-use
uname output: Linux MYSQL-PROD-05 4.4.59-92.24-default #1 SMP Thu Jun 22 
14:29:09 UTC 2017 (d11a83a) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:
        When using IFS and passing arguments to a function are the arguments 
are not divided at the IFS boundary unless the arguments are first concatenated 
to a single variable. 

Repeat-By:

The original bash scripts were written using bash-3.2 using IFS and passing 
argument to a function behaved as expected.
This is the bash-3.2 Configuration Information.
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc -I/usr/src/packages/BUILD/bash-3.2 
-L/usr/src/packages/BUILD/bash-3.2/../readline-5.2
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' 
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -fmessage-length=0 -O2 -Wall 
-D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables 
-fasynchronous-unwind-tables -g  -D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g 
-std=gnu89 -Wextra -Wno-unprototyped-calls -Wno-switch-enum 
-Wno-unused-variable -Wno-unused-parameter -ftree-loop-linear -pipe 
-DIMPORT_FUNCTIONS_DEF=0
uname output: Linux DBSSSC01 3.0.101-107-default #1 SMP Thu Jun 22 14:37:55 UTC 
2017 (414ea9f) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu
Bash Version: 3.2
Patch Level: 57
Release Status: release
-------------
But with 4.3

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.3 
-L/home/abuild/rpmbuild/BUILD/bash-4.3/../readline-6.3
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' 
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -fmessage-length=0 
-grecord-gcc-switches -fstack-protector -O2 -Wall -D_FORTIFY_SOURCE=2 
-funwind-tables -fasynchronous-unwind-tables -g  -D_GNU_SOURCE -DRECYCLES_PIDS 
-Wall -g -Wuninitialized -Wextra -Wno-unprototyped-calls -Wno-switch-enum 
-Wno-unused-variable -Wno-unused-parameter -Wno-parentheses -ftree-loop-linear 
-pipe -DBNC382214=0 -DIMPORT_FUNCTIONS_DEF=0 -fprofile-use
uname output: Linux MYSQL-PROD-05 4.4.59-92.24-default #1 SMP Thu Jun 22 
14:29:09 UTC 2017 (d11a83a) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu
Bash Version: 4.3
Patch Level: 42
Release Status: release
---------------
And bash 4.4

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu' 
-DCONF_VENDOR='unknown' -DLOCALEDIR='/home/gmccue/bash/bash-4.4/share/locale' 
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -g 
-O2 -Wno-parentheses -Wno-format-security
uname output: Linux DBSSSC01 3.0.101-107-default #1 SMP Thu Jun 22 14:37:55 UTC 
2017 (414ea9f) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu
Bash Version: 4.4
Patch Level: 0
Release Status: release
----------------
The IFS behaves differently depending on how the command is structured.
This is my test script. It demonstrates the behavior change between 3.2  and 
4.[3|4].

The function "doit" lists the individual arguments that it has received.
 
The function "doit" is called twice,  each time setting  IFS. 

The first time the function is called the arguments to "doit" are just listed 
in the function call.

The second time the function "doit" is called the arguments are concatenated in 
a variable and the variable is used as the argument to the function.
 
Here is test code.
----------------------------------
#!/bin/bash

echo BASH_VERSION=$BASH_VERSION

# list arguments
function doit
{
        declare -i argv_count=1
        echo "doit argc=$#"
        argv1=$1
        shift 1
        echo agv1=[$argv1]
        while [ $# -gt 0 ]
        do
                argv_count+=1;
                echo "argv_count=$argv_count[$1]"
                shift 1
        done
}

first_arg="1 "

## list arguments in the function call.
echo "first_arg=$first_arg"
echo "RESULT_A=\`doit \"\$first_arg\":2:3:4:\$PATH\'"
OIFS=$IFS
IFS=:
RESULT_A=`doit $first_arg:2:3:4:$PATH`
status=$?
IFS=$OIFS
echo -e "\$RESULT_A=\n$RESULT_A"
echo

## list arguments in a variable and use that in the function call.
all_args="$first_arg:2:3:4:$PATH"
echo "RESULT_B=\`doit \$all_args\'"
OIFS=$IFS
IFS=:
RESULT_B=`doit $all_args`
status=$?
IFS=$OIFS
echo -e "\$RESULT_B=\n$RESULT_B"
echo

# end of file
----------------------------------------
TEST RESULTS

Using bash3.2 both function calls act as expected. The arguments are divided 
for the function  at the IFS boundary.

BASH_VERSION=3.2.57(2)-release
first_arg=1 
RESULT_A=`doit "$first_arg":2:3:4:$PATH\'
$RESULT_A=
doit argc=14
agv1=[1 ]
argv_count=2[2]
argv_count=3[3]
argv_count=4[4]
argv_count=5[/usr/local/bin]
argv_count=6[/usr/bin]
argv_count=7[/bin]
argv_count=8[/usr/bin/X11]
argv_count=9[/usr/X11R6/bin]
argv_count=10[/usr/games]
argv_count=11[/opt/bin]
argv_count=12[/usr/lib/mit/bin]
argv_count=13[/usr/lib/mit/sbin]
argv_count=14[/u01/mysql/share/bin]

all_args="$first_arg:2:3:4:$PATH"
RESULT_B=`doit $all_args`
$RESULT_B=
doit argc=14
agv1=[1 ]
argv_count=2[2]
argv_count=3[3]
argv_count=4[4]
argv_count=5[/usr/local/bin]
argv_count=6[/usr/bin]
argv_count=7[/bin]
argv_count=8[/usr/bin/X11]
argv_count=9[/usr/X11R6/bin]
argv_count=10[/usr/games]
argv_count=11[/opt/bin]
argv_count=12[/usr/lib/mit/bin]
argv_count=13[/usr/lib/mit/sbin]
argv_count=14[/u01/mysql/share/bin]
  

But for bash  4.3 and 4.4(latest) the arguments passed to the first function 
call are not all divided at the IFS boundary.

In order to get all the arguments divided at the IFS boundary the arguments 
must first be concatenated into a variable and the variable used as the 
argument to the "doit" function. 

Here are the test Bash 4.3 results.

BASH_VERSION=4.3.42(1)-release
first_arg=1 
RESULT_A=`doit "$first_arg":2:3:4:$PATH\'
$RESULT_A=
doit argc=9
agv1=[1  2 3 4 /u01/mysql/5_7_19/usr/bin]
argv_count=2[/usr/local/bin]
argv_count=3[/usr/bin]
argv_count=4[/bin]
argv_count=5[/usr/bin/X11]
argv_count=6[/usr/X11R6/bin]
argv_count=7[/usr/games]
argv_count=8[/opt/bin]
argv_count=9[/u01/mysql/share/bin]

RESULT_B=`doit $all_args\'
$RESULT_B=
doit argc=13
agv1=[1 ]
argv_count=2[2]
argv_count=3[3]
argv_count=4[4]
argv_count=5[/u01/mysql/5_7_19/usr/bin]
argv_count=6[/usr/local/bin]
argv_count=7[/usr/bin]
argv_count=8[/bin]
argv_count=9[/usr/bin/X11]
argv_count=10[/usr/X11R6/bin]
argv_count=11[/usr/games]
argv_count=12[/opt/bin]
argv_count=13[/u01/mysql/share/bin]


Here is the test Bash 4.4(latest) results

BASH_VERSION=4.4.0(1)-release
first_arg=1 
RESULT_A=`doit "$first_arg":2:3:4:$PATH\'
$RESULT_A=
doit argc=10
agv1=[1  2 3 4 /usr/local/bin]
argv_count=2[/usr/bin]
argv_count=3[/bin]
argv_count=4[/usr/bin/X11]
argv_count=5[/usr/X11R6/bin]
argv_count=6[/usr/games]
argv_count=7[/opt/bin]
argv_count=8[/usr/lib/mit/bin]
argv_count=9[/usr/lib/mit/sbin]
argv_count=10[/u01/mysql/share/bin]

all_args="$first_arg:2:3:4:$PATH"
RESULT_B=`doit $all_args`
$RESULT_B=
doit argc=14
agv1=[1 ]
argv_count=2[2]
argv_count=3[3]
argv_count=4[4]
argv_count=5[/usr/local/bin]
argv_count=6[/usr/bin]
argv_count=7[/bin]
argv_count=8[/usr/bin/X11]
argv_count=9[/usr/X11R6/bin]
argv_count=10[/usr/games]
argv_count=11[/opt/bin]
argv_count=12[/usr/lib/mit/bin]
argv_count=13[/usr/lib/mit/sbin]
argv_count=14[/u01/mysql/share/bin]

As has been demonstrated the Bash 4.[3|4] test will only divide all the 
arguments at the IFS boundary when the function call is made with a single 
variable.


        

Glenn McCue

Shared Services Canada / Services partag├ęs Canada 
8 Colonnade, Room 3020,
Ottawa, ON, K1A 0K9
Address Locator: 6901 

Phone:  (613) 220-5329
Email: address@hidden 
Fax: (613) 957-9942





reply via email to

[Prev in Thread] Current Thread [Next in Thread]