rschupp / PAR-Packer

(perl) Generate stand-alone executables, perl scripts and PAR files https://metacpan.org/pod/PAR::Packer
Other
48 stars 13 forks source link

Revert "remove PAR_ARGV_*, PAR_ARGC stuff, not needed" #4

Closed andrewgregory closed 7 years ago

andrewgregory commented 7 years ago

Removing PARARGV* and PAR_ARGC breaks command-line parsing on Windows. Arguments with spaces get split into separate arguments.

This reverts commit 4cd9683fab1cd0839704c4c1708b868b7c76e683.

I haven't dug into PAR/PP internals, but I believe that this is caused by the fact that on Windows programs receive the command as a single string and have to parse out ARGC and ARGV individually. The bootstrap executable parses them correctly, but then they get stringified improperly when handing off to the packed perl/script executable.

Some references in Windows argument passing: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ http://blogs.perl.org/users/graham_knop/2011/12/using-system-or-exec-safely-on-windows.html

The bug can be seen with the following script:

print join(':', @ARGV)

Packed with PP 1.36, a.exe "foo bar" prints foo bar. Packed with PP 1.37, a.exe "foo bar" prints foo:bar.

rschupp commented 7 years ago

Nope. If you think you've observed bug, please open a bug report on rt.cpan.org.

I haven't dug into PAR/PP internals

Otherwise you would have found out that we don't use system or exec, we use spawnvp().

andrewgregory commented 7 years ago

I've opened a bug, but I don't think spawnvp works the way you think it does.

test.c:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv) {
    char *arg[] = {"test2.exe", "foo", "bar baz", NULL };
    return spawnvp(P_WAIT, arg[0], arg);
}

test2.c:

#include <stdio.h>

int main(int argc, char **argv) {
    int i;
    for(i = 1; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }
    return 0;
}
gcc test.c -o test.exe
gcc test2.c -o test2.exe
test.exe

prints

1: foo
2: bar
3: baz
rschupp commented 7 years ago

Fixed this another way in a076d4c4d5004e395dc8311d4e4729a975e815a2 by quoting elements of argv if necessary.