Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Greg Wooledge
On Mon, Feb 11, 2013 at 06:50:49PM +0100, Dashing wrote:
 $ ./pe 'mplayer foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7'
 :--Mistake--:
 :--Mistake--:

Whatever you're doing, it's wrong.

./pe mplayer foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7

#!/bin/bash
prog=$1
shift
exec $prog extra args go here $@

THAT is how a wrapper should be done.  Do not combine a program and its
arguments all together into a single argument and then try to parse it
apart.



Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Greg Wooledge
On Tue, Feb 12, 2013 at 02:37:03PM +0100, Dashing wrote:
 For my purposes this is irrelevant, because the nature of the 
 script from which my example code derived is tab completion. 
 READLINE_LINE will contain mplayer foo1\ foo2\ etc.

Then you are still doing something wrong.

imadev:~$ args Tori\ Amos\ -\ Mr.\ Zebra.ogg 
1 args: Tori Amos - Mr. Zebra.ogg

There are no literal backslashes in an argument that is produced by
tab completion.  The backslashes are a form of quoting, and they are
removed by the calling shell during the quote removal phase.

If you believe you have found a bug in parameter expansion, then
simplify the example so that it directly demonstrates the bug.  For
example,

foo='some thing with \ \ \ \ backslashes'
echo ${foo##* }
echo I expected to see 'blah'

If you are playing around with read -e, then your script should CONTAIN
that.  And if you are reading shell commands in a shell script using
read -e and then attempting to parse them the way a shell would, then you
should reevaluate your goals, or the methods you are attempting to use to
attain them, because writing a shell in a shell is kinda wonky, isn't it?



Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Dashing
On Tue, 12 Feb 2013 14:45:26 +0100 Greg Wooledge 
wool...@eeg.ccf.org wrote:
There are no literal backslashes in an argument that is
produced by tab completion.  The backslashes are a form
of quoting, and they are removed by the calling shell
during the quote removal phase.

When bind -x sets READLINE_LINE backslashes are kept intact. What I 
meant was that I wrote my own tab completion.

If you believe you have found a bug in parameter expansion,
then simplify the example so that it directly demonstrates
the bug.

As I showed in the output, it does not happen all the time. Even 
the same value of $rest one time works and another time does not. 
Therefore, looping over a bunch of items is required.




Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Andreas Schwab
Greg Wooledge wool...@eeg.ccf.org writes:

 Then you are still doing something wrong.

No matter how badly the script is written, bash should execute it
properly, which it doesn't.  Try running it under valgrind in a
multibyte locale and you will see the error immediately:

==18677== Conditional jump or move depends on uninitialised value(s)
==18677==at 0x4504B6: xdupmbstowcs (xmbsrtowcs.c:240)
==18677==by 0x42A43F: remove_pattern (subst.c:3964)
==18677==by 0x42F3B7: parameter_brace_expand (subst.c:4543)
==18677==by 0x466E48: param_expand (subst.c:7651)
==18677==by 0x467C91: expand_word_internal (subst.c:8139)
==18677==by 0x467F24: expand_word_internal (subst.c:8285)
==18677==by 0x42F981: call_expand_word_internal.constprop.15 (subst.c:3197)
==18677==by 0x42FD94: expand_string_assignment (subst.c:3283)
==18677==by 0x466BB3: expand_string_if_necessary (subst.c:3046)
==18677==by 0x47632F: do_assignment_internal (subst.c:2772)
==18677==by 0x469726: expand_word_list_internal (subst.c:2866)
==18677==by 0x45CCB3: execute_simple_command (execute_cmd.c:3776)
==18677== 

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
And now for something completely different.



Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Chet Ramey
On 2/12/13 11:37 AM, Andreas Schwab wrote:
 Greg Wooledge wool...@eeg.ccf.org writes:
 
 Then you are still doing something wrong.
 
 No matter how badly the script is written, bash should execute it
 properly, which it doesn't.  Try running it under valgrind in a
 multibyte locale and you will see the error immediately:

There is an error in xdupmbstowcs, but beyond that the output from
valgrind is fairly useless, all the more so because you didn't post
the version (most likely the 4.2 patch level) you're using.  If
you're using patch 42, the line number corresponds to a return of a
value that's always initialized.

In any event, the problem is in a different place, and I've fixed it
for the next version.

Chet


 
 ==18677== Conditional jump or move depends on uninitialised value(s)
 ==18677==at 0x4504B6: xdupmbstowcs (xmbsrtowcs.c:240)
 ==18677==by 0x42A43F: remove_pattern (subst.c:3964)
 ==18677==by 0x42F3B7: parameter_brace_expand (subst.c:4543)
 ==18677==by 0x466E48: param_expand (subst.c:7651)
 ==18677==by 0x467C91: expand_word_internal (subst.c:8139)
 ==18677==by 0x467F24: expand_word_internal (subst.c:8285)
 ==18677==by 0x42F981: call_expand_word_internal.constprop.15 
 (subst.c:3197)
 ==18677==by 0x42FD94: expand_string_assignment (subst.c:3283)
 ==18677==by 0x466BB3: expand_string_if_necessary (subst.c:3046)
 ==18677==by 0x47632F: do_assignment_internal (subst.c:2772)
 ==18677==by 0x469726: expand_word_list_internal (subst.c:2866)
 ==18677==by 0x45CCB3: execute_simple_command (execute_cmd.c:3776)
 ==18677== 
 
 Andreas.
 


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Chet Ramey
 Bash version: 4.2.042 
 
 I have a script that behaves erratically:

Thanks for the report.  The reason it is erratic and not always
reproducible in the same spot is that it is the result of an array
bounds error, and so depends on the contents of memory beyond the
end of a string.

I've fixed the problem, and the fix will be in the next release.  If
you're interested in the fix, I've attached a patch.

Chet

*** ../bash-4.2-patched/lib/glob/xmbsrtowcs.c   2012-07-08 21:53:19.0 
-0400
--- lib/glob/xmbsrtowcs.c   2013-02-12 12:00:39.0 -0500
***
*** 217,220 
--- 217,226 
n = mbsnrtowcs(wsbuf+wcnum, p, nms, wsbuf_size-wcnum, state);
  
+   if (n == 0  p == 0)
+   {
+ wsbuf[wcnum] = L'\0';
+ break;
+   }
+ 
/* Compensate for taking single byte on wcs conversion failure above. */
if (wcslength == 1  (n == 0 || n == (size_t)-1))
***
*** 222,226 
  state = tmp_state;
  p = tmp_p;
! wsbuf[wcnum++] = *p++;
}
else
--- 228,238 
  state = tmp_state;
  p = tmp_p;
! wsbuf[wcnum] = *p;
! if (*p == 0)
!   break;
! else
!   {
! wcnum++; p++;
!   }
}
else

``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/


Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Bernd Eggink

On 11.02.2013 18:50, Dashing wrote:

Bash version: 4.2.042

I have a script that behaves erratically:
=
#! /bin/bash
last=${1##* }
rest=${1% *}
while [[ ${rest: -1} == '\' ]]; do
last=${rest##* } $last
oldrest=$rest
rest=${rest% *}
if [[ $oldrest == $rest ]]; then
echo :--Mistake--:
#   sleep 0.01
#   rest=${rest% *}
#   if [[ $oldrest == $rest ]]; then
#   echo 'unable to interpret'
#   break
#   fi
fi
done
echo REST:$rest:
echo LAST:$last:
=
$ ./pe 'mplayer foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7'
:--Mistake--:
:--Mistake--:
REST:mplayer:
LAST:foo1\ foo1\ foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7:
=

What happens is that rest=${rest% *} doesn't always update $rest,
even when there are spaces left in $rest.
Meanwhile last=${rest##* } $last works every time.
In the above example it got stuck twice when $rest was mplayer
foo1\. It tends to vary wildly.


The script runs fine if you omit the superfluous blank in the ${rest: 
-1} expression:


while [[ ${rest:-1} == '\' ]]; do

If the script behaves indeterministic, it is probably a bash bug.

Regards,
Bernd



--
www.sudrala.de


Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Dashing
On Tue, 12 Feb 2013 18:02:05 +0100 Chet Ramey
I've fixed the problem, and the fix will be in the next release.  

Thank you, Chet!

On Tue, 12 Feb 2013 10:13:46 +0100 Bernd Eggink
superfluous blank in the ${rest: -1} expression

Bernd, this blank makes a big difference:
${rest: -1} last character of $rest
${rest:-1} $rest or 1 if $rest is empty




Re: [Parameter Expansion] bug in ${variable% *}

2013-02-12 Thread Bernd Eggink

On 12.02.2013 18:50, Dashing wrote:

On Tue, 12 Feb 2013 18:02:05 +0100 Chet Ramey

I've fixed the problem, and the fix will be in the next release.


Thank you, Chet!

On Tue, 12 Feb 2013 10:13:46 +0100 Bernd Eggink

superfluous blank in the ${rest: -1} expression


Bernd, this blank makes a big difference:
${rest: -1} last character of $rest
${rest:-1} $rest or 1 if $rest is empty



You're right, of course. Sigh. Fortunately I've not yet fallen into that 
pithole...


Bernd

--
www.sudrala.de


[Parameter Expansion] bug in ${variable% *}

2013-02-11 Thread Dashing
Bash version: 4.2.042 

I have a script that behaves erratically:
=
#! /bin/bash
last=${1##* }
rest=${1% *}
while [[ ${rest: -1} == '\' ]]; do
last=${rest##* } $last
oldrest=$rest
rest=${rest% *}
if [[ $oldrest == $rest ]]; then
echo :--Mistake--:
#   sleep 0.01
#   rest=${rest% *}
#   if [[ $oldrest == $rest ]]; then
#   echo 'unable to interpret'
#   break
#   fi
fi
done
echo REST:$rest:
echo LAST:$last:
=
$ ./pe 'mplayer foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7'
:--Mistake--:
:--Mistake--:
REST:mplayer:
LAST:foo1\ foo1\ foo1\ foo2\ foo3\ 4\ 5\ foo6\ 7:
=

What happens is that rest=${rest% *} doesn't always update $rest, 
even when there are spaces left in $rest.
Meanwhile last=${rest##* } $last works every time.
In the above example it got stuck twice when $rest was mplayer 
foo1\. It tends to vary wildly.

I have commented out some code including sleep that sometimes helps 
make the parameter expansion work. This commented out code also 
avoids an infinite loop which is triggerable in a normal way with 
an argument of:
command\ filename

Thanks,
Dashing