git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [BUG] [PATCH]: run-command.c
@ 2016-10-21  5:50 Duncan Roe
  2016-10-21  9:00 ` Jeff King
  0 siblings, 1 reply; 4+ messages in thread
From: Duncan Roe @ 2016-10-21  5:50 UTC (permalink / raw)
  To: git

prepare_shell_cmd() executes /bin/sh with superfluous arguments on all but
single-word shell commands.

For example, if .git/config has this alias (the sleep is to leave time to
examine output from ps, &c.):

[alias]
	tryme = "!echo $PWD;sleep 600"

running "git tryme" in one console and checking what it does in another

--- 1st xterm

16:42:12$ git tryme
/usr/src/git/.git
echo $PWD;sleep 600: line 1:  2602 Terminated              sleep 600
16:43:15$


--- 2nd xterm

16:42:06$ ps axf|grep -A2 trym[e]
 2599 pts/4    S+     0:00      \_ git tryme
 2601 pts/4    S+     0:00          \_ /bin/sh -c echo $PWD;sleep 600 echo $PWD;sleep 600
 2602 pts/4    S+     0:00              \_ sleep 600
16:42:45$ cat /proc/2601/cmdline | xargs -0 -n1 echo
/bin/sh
-c
echo $PWD;sleep 600
echo $PWD;sleep 600
16:43:04$ kill 2602
16:43:15$

---

There is an extra "-c" argument. This is caused by a missing "else", fixed by
the appended patch,

Cheers ... Duncan.

----------8<-------------------

--- a/run-command.c
+++ b/run-command.c
@@ -182,8 +182,8 @@ static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
 		else
 			argv_array_pushf(out, "%s \"$@\"", argv[0]);
 	}
-
-	argv_array_pushv(out, argv);
+	else
+		argv_array_pushv(out, argv);
 	return out->argv;
 }


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] [PATCH]: run-command.c
  2016-10-21  5:50 [BUG] [PATCH]: run-command.c Duncan Roe
@ 2016-10-21  9:00 ` Jeff King
  2016-10-21 11:07   ` Duncan Roe
  2016-10-21 17:19   ` Junio C Hamano
  0 siblings, 2 replies; 4+ messages in thread
From: Jeff King @ 2016-10-21  9:00 UTC (permalink / raw)
  To: git

On Fri, Oct 21, 2016 at 04:50:13PM +1100, Duncan Roe wrote:

> For example, if .git/config has this alias (the sleep is to leave time to
> examine output from ps, &c.):
> 
> [alias]
> 	tryme = "!echo $PWD;sleep 600"
>
> [...]
> 16:42:06$ ps axf|grep -A2 trym[e]
>  2599 pts/4    S+     0:00      \_ git tryme
>  2601 pts/4    S+     0:00          \_ /bin/sh -c echo $PWD;sleep 600 echo $PWD;sleep 600
>  2602 pts/4    S+     0:00              \_ sleep 600
> 16:42:45$ cat /proc/2601/cmdline | xargs -0 -n1 echo
> /bin/sh
> -c
> echo $PWD;sleep 600
> echo $PWD;sleep 600

This duplicated argument is expected and normal. The arguments after "-c
whatever" become positional parameters $0, $1, etc. The actual script
arguments start at "$1", and "$0" is typically the "script name".
So you have to stick some placeholder value in the "$0" slot, so that
the sub-script can find the actual arguments. E.g., try:

  sh -c '
    for i in "$@"; do
      echo "got $i"
    done
  ' one two three

it will print only:

  got two
  got three

But if you stick a placeholder there, it works:

  sh -c '
    for i in "$@"; do
      echo "got $i"
    done
  ' placeholder one two three

The value of the placeholder does not matter to the shell. But it is
accessible to the script inside via $0:

  sh -c '
    echo "\$0 = $0"
    echo "\$1 = $1"
    echo "\$2 = $2"
    echo "\$3 = $3"
  ' placeholder one two three

Since our script does not have a filename, we just stick the script
contents there (which is really just a convention, and one I doubt
anybody is really relying on, but there's no point in breaking it now).

> --- a/run-command.c
> +++ b/run-command.c
> @@ -182,8 +182,8 @@ static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
>  		else
>  			argv_array_pushf(out, "%s \"$@\"", argv[0]);
>  	}
> -
> -	argv_array_pushv(out, argv);
> +	else
> +		argv_array_pushv(out, argv);
>  	return out->argv;
>  }

Try running "make test" with this. Lots of things break, because we are
not sending the positional parameters to the shell script at all.

If we just cared about the positional parmeters, we _could_ do something
like:

  if (argv[0]) {
	argv_array_push(out, "sh");
	argv_array_pushv(out, argv + 1);
  }

That would omit "$0" entirely when we have no positional parameters (and
the shell generally fills in "sh" there itself), and provide a dummy
"sh" value when we need to use it as a placeholder.

But again, there's no real value in breaking the existing convention.

-Peff

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] [PATCH]: run-command.c
  2016-10-21  9:00 ` Jeff King
@ 2016-10-21 11:07   ` Duncan Roe
  2016-10-21 17:19   ` Junio C Hamano
  1 sibling, 0 replies; 4+ messages in thread
From: Duncan Roe @ 2016-10-21 11:07 UTC (permalink / raw)
  To: git

On Fri, Oct 21, 2016 at 05:00:29AM -0400, Jeff King wrote:
> On Fri, Oct 21, 2016 at 04:50:13PM +1100, Duncan Roe wrote:
>
> > For example, if .git/config has this alias (the sleep is to leave time to
> > examine output from ps, &c.):
> >
> > [alias]
> > 	tryme = "!echo $PWD;sleep 600"
> >
> > [...]
> > 16:42:06$ ps axf|grep -A2 trym[e]
> >  2599 pts/4    S+     0:00      \_ git tryme
> >  2601 pts/4    S+     0:00          \_ /bin/sh -c echo $PWD;sleep 600 echo $PWD;sleep 600
> >  2602 pts/4    S+     0:00              \_ sleep 600
> > 16:42:45$ cat /proc/2601/cmdline | xargs -0 -n1 echo
> > /bin/sh
> > -c
> > echo $PWD;sleep 600
> > echo $PWD;sleep 600
>
> This duplicated argument is expected and normal. The arguments after "-c
> whatever" become positional parameters $0, $1, etc. The actual script
> arguments start at "$1", and "$0" is typically the "script name".
> So you have to stick some placeholder value in the "$0" slot, so that
> the sub-script can find the actual arguments. E.g., try:
>
>   sh -c '
>     for i in "$@"; do
>       echo "got $i"
>     done
>   ' one two three
>
> it will print only:
>
>   got two
>   got three
>
> But if you stick a placeholder there, it works:
>
>   sh -c '
>     for i in "$@"; do
>       echo "got $i"
>     done
>   ' placeholder one two three
>
> The value of the placeholder does not matter to the shell. But it is
> accessible to the script inside via $0:
>
>   sh -c '
>     echo "\$0 = $0"
>     echo "\$1 = $1"
>     echo "\$2 = $2"
>     echo "\$3 = $3"
>   ' placeholder one two three
>
> Since our script does not have a filename, we just stick the script
> contents there (which is really just a convention, and one I doubt
> anybody is really relying on, but there's no point in breaking it now).
>
> > --- a/run-command.c
> > +++ b/run-command.c
> > @@ -182,8 +182,8 @@ static const char **prepare_shell_cmd(struct argv_array *out, const char **argv)
> >  		else
> >  			argv_array_pushf(out, "%s \"$@\"", argv[0]);
> >  	}
> > -
> > -	argv_array_pushv(out, argv);
> > +	else
> > +		argv_array_pushv(out, argv);
> >  	return out->argv;
> >  }
>
> Try running "make test" with this. Lots of things break, because we are
> not sending the positional parameters to the shell script at all.
>
> If we just cared about the positional parmeters, we _could_ do something
> like:
>
>   if (argv[0]) {
> 	argv_array_push(out, "sh");
> 	argv_array_pushv(out, argv + 1);
>   }
>
> That would omit "$0" entirely when we have no positional parameters (and
> the shell generally fills in "sh" there itself), and provide a dummy
> "sh" value when we need to use it as a placeholder.
>
> But again, there's no real value in breaking the existing convention.
>
> -Peff
Agreed - tests 110 and 111 in t1300-repo-config.sh fail. After that, "make test"
gives up, losing about 14000 lines of output.

Sorry for the noise,

Cheers ... Duncan.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] [PATCH]: run-command.c
  2016-10-21  9:00 ` Jeff King
  2016-10-21 11:07   ` Duncan Roe
@ 2016-10-21 17:19   ` Junio C Hamano
  1 sibling, 0 replies; 4+ messages in thread
From: Junio C Hamano @ 2016-10-21 17:19 UTC (permalink / raw)
  To: Jeff King; +Cc: git

Jeff King <peff@peff.net> writes:

>> 16:42:45$ cat /proc/2601/cmdline | xargs -0 -n1 echo
>> /bin/sh
>> -c
>> echo $PWD;sleep 600
>> echo $PWD;sleep 600
>
> This duplicated argument is expected and normal.

Well explained.  Thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-10-21 17:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-21  5:50 [BUG] [PATCH]: run-command.c Duncan Roe
2016-10-21  9:00 ` Jeff King
2016-10-21 11:07   ` Duncan Roe
2016-10-21 17:19   ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).