Control: reassign 1112461 eperl
Control: severity -1 important
Control: forcemerge -1 1112461
Control: tags -1 + patch

[CC += Niko in case this is actually a perl bug and I'm not holding it wrong,
 please cf. section starting "Steps to repro"]

I can reproduce this.

However: this does /not/ appear to be an eperl thing;
or at least, not exclusively.
I'm running the same configuration in a bookworm chroot
and a trixie chroot, and I see:

  bookworm  bookworm bin:eperl            full output
  bookworm  trixie   bin:eperl (rebuilt)  full output
  bookworm  git ossp-eperl 2.2.15         full output
  trixie    trixie   bin:eperl            no   output
  trixie    bookworm bin:eperl (rebuilt)  full output
  trixie    git ossp-eperl 2.2.15         no   output

(where "no output" is one line, like it is for you, but that line is
   GATEWAY_INTERFACE = CGI/1.1
 so just one, but a different one

So this looks like some interaction between eperl
/and/ the rest of the system
(apache2? CGI.pm? perl 2.38 -> 2.40?).

(apache2? probably not, a CGI of
   #!/bin/sh
   echo content-type: text/plain
   echo
   exec env
 is the same (sans like PATH and SERVER_SOFTWARE)
 between bookworm and trixie.)

I get full output on trixie + trixie bin:perl
when I run eperl -w instead of eperl
(through a shell "exec eperl ..." wrapper).
Likewise for -x.

...

I've actually isolated the repro to
  env -i GATEWAY_INTERFACE='CGI/1.1' PATH_TRANSLATED='/srv/a.phtml' ./eperl
where adding -x, -w, /or/ -mc makes it work.

-mc is notable because this is /already/ CGI mode.
I can't otherwise ascertain any meaningful difference.

...actually even passing an empty string as the first argument works.
what the hell.

There appears to be no effect to this that I can see. Except that it
makes it work. Hell, even
  if(!argv[optind])
    argv[optind] = "";
after the getopt loop fixes it(!?):
-- >8 --
diff --git a/eperl_main.c b/eperl_main.c
index 13417db..237b093 100644
--- a/eperl_main.c
+++ b/eperl_main.c
@@ -347,6 +347,9 @@ int main(int argc, char **argv)
                 return EX_USAGE;
         }
 
+if(!argv[optind])
+argv[optind]="";
+
     /*
      *  determine source filename and runtime mode
      */
-- >8 --

But only with perl 5.40. I can't reproduce this on perl 5.36.

Steps to repro:
1. git clone https://git.sr.ht/~nabijaczleweli/ossp-eperl
   (I'm testing @ 97313d69c99b72863b9dd23c442c4fa881b483b3
    which is equivalent to ePerl_2_2_15 and src:eperl 2.2.15-1)
2. autoreconf -fi && ./configure && make eperl
3. echo '<? foreach my $var (keys %ENV) {print "$var = $ENV{$var}\n"; } !>' > 
b.phtml
4. env -i GATEWAY_INTERFACE=CGI/1.1 PATH_TRANSLATED="$PWD/b.phtml" ./eperl
5. env -i GATEWAY_INTERFACE=CGI/1.1 PATH_TRANSLATED="$PWD/b.phtml" ./eperl -x
6. env -i GATEWAY_INTERFACE=CGI/1.1 PATH_TRANSLATED="$PWD/b.phtml" ./eperl ''

5/6 will have the whole environment on bookworm and trixie.
4   will have the whole environment on bookworm (libperl5.36:i386 
5.36.0-7+deb12u2)
but will only have one variable on trixie       (libperl5.40:i386 5.40.1-6).

The arguments have no effect on the generated code, environment,
or libperl parameters.

If you apply the patch above
(turning the argument sexion of the environment block
 from (2, {"./eperl", NULL}) to (2, {"./eperl", ""}))
4 will also have the whole environment on trixie.

This stinks of UB, but GCC UBsan doesn't pick up anything.
But I haven't been able to reduce this to a minimal reproducer.

I have isolated this to Perl5_Run() doing
    // A
    /*  now allocate the Perl interpreter  */
    PERL_SYS_INIT3(&myargc, &myargv, &environ);
    my_perl = perl_alloc();
    perl_construct(my_perl);
    // B

    /*  now parse the script!
        NOTICE: At this point, the script gets
        only _parsed_, not evaluated/executed!  */
    rc = perl_parse(my_perl, Perl5_XSInit, myargc, myargv, environ);
    // C
where dumping environ at A and B reveals it's full,
but dumping environ at C reveals it's been truncated.

Applying the following, which should, by all accounts, be a no-op,
actually fixes this: environ is undamaged, and the result from the
program is as-expected.

-- >8 --
diff --git a/eperl_perl5.c b/eperl_perl5.c
index 9e66772..a46679a 100644
--- a/eperl_perl5.c
+++ b/eperl_perl5.c
@@ -126,14 +126,14 @@ int Perl5_Run(int myargc, char **myargv, enum 
runtime_mode mode, bool fCheck, bo
 
 
     /*  now allocate the Perl interpreter  */
-    PERL_SYS_INIT3(&myargc, &myargv, &environ);
+    PERL_SYS_INIT(&myargc, &myargv);
     my_perl = perl_alloc();
     perl_construct(my_perl);
 
     /*  now parse the script!
         NOTICE: At this point, the script gets
         only _parsed_, not evaluated/executed!  */
-    rc = perl_parse(my_perl, Perl5_XSInit, myargc, myargv, environ);
+    rc = perl_parse(my_perl, Perl5_XSInit, myargc, myargv, NULL);
     if (rc != 0) {
         IO_restore_stderr();
         stdfd_thread_cu(&perlstderr, &stderr_thread);
-- >8 --

This looks like a good patch to include upstream anyway?
but maybe I'm missing something obvious.

Best,

Attachment: signature.asc
Description: PGP signature

Reply via email to