Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errno ($!) not evaluated to a error message string (5.10.0 in taint mode) #9613

Closed
p5pRT opened this issue Jan 5, 2009 · 14 comments
Closed

Comments

@p5pRT
Copy link

p5pRT commented Jan 5, 2009

Migrated from rt.perl.org#61976 (status was 'open')

Searchable as RT61976$

@p5pRT
Copy link
Author

p5pRT commented Jan 5, 2009

From Mark.Martinec@ijs.si

Created by root@patsy.ijs.si

With Perl 5.10.0 in taint mode, evaluating a $! variable in
a string context does not yield a system error message text,
but gives a numeric errno code.

The problem is reproducible with an EPIPE error, although
I can not reproduce it with a more trivial I/O error.

The problem is reproducible on all platforms that I tried​:
FreeBSD 6.3 in 32-bit mode, FreeBSD 7.0 in 64-bit mode,
and on Linux 2.6.27.9-159.fc10.x86_64.

The following example illustrates the problem.
Standard output is piped into a program which does not read from
its stdin, such as a 'true', intentionally causing a broken pipe​:

$ date | /usr/local/bin/perl5.10.0 -T -e '
  $|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
  print $s or die "error writing​: $!\n"' | true
error writing​: 32

The same command with perl 5.8.8 works as expected,
reporting a 'Broken pipe' instead of a '32'​:

$ date | /usr/local/bin/perl5.8.8 -T -e '
  $|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
  print $s or die "error writing​: $!\n"' | true
error writing​: Broken pipe

Without a -T switch even the perl5.10.0 yields a correct result​:

$ date | /usr/local/bin/perl5.10.0 -e '
  $|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
  print $s or die "error writing​: $!\n"' | true
error writing​: Broken pipe

Perl Info

Flags:
    category=core
    severity=medium

This perlbug was built using Perl v5.8.8 - Fri Nov 21 17:20:57 UTC 2008
It is being executed now by  Perl v5.10.0 - Fri Nov 21 16:22:04 UTC 2008.

Site configuration information for perl v5.10.0:

Configured by root at Fri Nov 21 16:22:04 UTC 2008.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
  Platform:
    osname=freebsd, osvers=6.3-release-p4, archname=i386-freebsd
    uname='freebsd patsy.ijs.si 6.3-release-p4 freebsd 6.3-release-p4 #1: sun sep 14 11:22:58 cest 2008 lesi@patsy.ijs.si:usrobjusrsrcsyspatsy i386 '
    config_args='-de'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -I/usr/local/include',
    optimize='-O',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='3.4.6 [FreeBSD] 20060305', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-Wl,-E  -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib
    libs=-lm -lcrypt -lutil -lc
    perllibs=-lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib'

Locally applied patches:
    defined-or


@INC for perl v5.10.0:
    /usr/local/lib/perl5/5.10.0/i386-freebsd
    /usr/local/lib/perl5/5.10.0
    /usr/local/lib/perl5/site_perl/5.10.0/i386-freebsd
    /usr/local/lib/perl5/site_perl/5.10.0
    .


Environment for perl v5.10.0:
    HOME=/root
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/root/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/root/bin:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 6, 2009

From @rgs

2009/1/5 via RT Mark Martinec <perlbug-followup@​perl.org>​:

With Perl 5.10.0 in taint mode, evaluating a $! variable in
a string context does not yield a system error message text,
but gives a numeric errno code.

The problem is reproducible with an EPIPE error, although
I can not reproduce it with a more trivial I/O error.

The problem is reproducible on all platforms that I tried​:
FreeBSD 6.3 in 32-bit mode, FreeBSD 7.0 in 64-bit mode,
and on Linux 2.6.27.9-159.fc10.x86_64.

The following example illustrates the problem.
Standard output is piped into a program which does not read from
its stdin, such as a 'true', intentionally causing a broken pipe​:

$ date | /usr/local/bin/perl5.10.0 -T -e '
$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

I would conjecturate a bad interaction between taint magic and \0-magic.
The question is​: why is $! tainted here ?

@p5pRT
Copy link
Author

p5pRT commented Jan 6, 2009

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 7, 2009

From @Tux

On Tue, 6 Jan 2009 14​:32​:10 +0100, "Rafael Garcia-Suarez"
<rgarciasuarez@​gmail.com> wrote​:

2009/1/5 via RT Mark Martinec <perlbug-followup@​perl.org>​:

With Perl 5.10.0 in taint mode, evaluating a $! variable in
a string context does not yield a system error message text,
but gives a numeric errno code.

The problem is reproducible with an EPIPE error, although
I can not reproduce it with a more trivial I/O error.

The problem is reproducible on all platforms that I tried​:
FreeBSD 6.3 in 32-bit mode, FreeBSD 7.0 in 64-bit mode,
and on Linux 2.6.27.9-159.fc10.x86_64.

The following example illustrates the problem.
Standard output is piped into a program which does not read from
its stdin, such as a 'true', intentionally causing a broken pipe​:

$ date | /usr/local/bin/perl5.10.0 -T -e '
$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

I would conjecturate a bad interaction between taint magic and \0-magic.
The question is​: why is $! tainted here ?

$ date | perl -MDP -T -le'$|=1;$SIG{PIPE}="IGNORE";my$s=<STDIN>;print$s;print STDERR DPeek$_ for DDual$\!,1;print DDump_IO *STDERR,$\!,2' | true
PV("Broken pipe"\0)
SV_UNDEF
NV(32)
SV_UNDEF
IV(3)
SV = PVMG(0x880060) at 0x8d51f8
  REFCNT = 1
  FLAGS = (GMG,SMG,pNOK,pPOK)
  IV = 0
  NV = 32
  PV = 0x86e760 "Broken pipe"\0
  CUR = 11
  LEN = 16
  MAGIC = 0x8d69c0
  MG_VIRTUAL = &PL_vtbl_sv
  MG_TYPE = PERL_MAGIC_sv(\0)
  MG_OBJ = 0x8d5210
  MG_LEN = 1
  MG_PTR = 0x8d6a70 "!"

--
H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/
using & porting perl 5.6.2, 5.8.x, 5.10.x, 5.11.x on HP-UX 10.20, 11.00,
11.11, 11.23, and 11.31, SuSE 10.1, 10.3, and 11.0, AIX 5.2, and Cygwin.
http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/
http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

@p5pRT
Copy link
Author

p5pRT commented May 28, 2009

From p5p@spam.wizbit.be

On Tue Jan 06 05​:32​:44 2009, rafael wrote​:

2009/1/5 via RT Mark Martinec <perlbug-followup@​perl.org>​:

With Perl 5.10.0 in taint mode, evaluating a $! variable in
a string context does not yield a system error message text,
but gives a numeric errno code.

The problem is reproducible with an EPIPE error, although
I can not reproduce it with a more trivial I/O error.

The problem is reproducible on all platforms that I tried​:
FreeBSD 6.3 in 32-bit mode, FreeBSD 7.0 in 64-bit mode,
and on Linux 2.6.27.9-159.fc10.x86_64.

The following example illustrates the problem.
Standard output is piped into a program which does not read from
its stdin, such as a 'true', intentionally causing a broken pipe​:

$ date | /usr/local/bin/perl5.10.0 -T -e '
$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

Binary search​:

----Program----
#!/usr/bin/perl

system( q(date | ) . $^X . q( -Te '$|=1; $SIG{PIPE}="IGNORE"; my
$s=<STDIN>;print $s or die "error writing​: $!\n"' | true));

----Output of .../pZl8r9Q/perl-5.9.3@​27174/bin/perl----
error writing​: Broken pipe

----EOF ($?='0')----
----Output of .../pBlLfHt/perl-5.9.3@​27176/bin/perl----
error writing​: 32

----EOF ($?='0')----
Need a perl between 27174 and 27176
No patch available between 27174 and 27176

http​://public.activestate.com/cgi-bin/perlbrowse/p/27176
Change 27176 by nicholas@​nicholas-fangorn on 2006/02/13 21​:46​:13

  Ensure that public I, N and P flags are off when SvTAINT is
called on
  something that already has taint magic.

I would conjecturate a bad interaction between taint magic and \0-
magic.
The question is​: why is $! tainted here ?

It is my understanding that $! is supposed to be tainted because it is
'locale information'. (as in, depends on the value of $ENV{LC_MESSAGES})

But the tainted string should still be shown in the die message since
it does not affect something else outside the program...

What is also intresting​:

$ date | perl-5.10.0 -Te '$|=1; $SIG{PIPE}="IGNORE"; my
$s=<STDIN>;print $s or die "error writing​: $!\n"' | true
error writing​: 32

$ date | /opt/perl/bin/perl5100 -Te '$|=1; $SIG{PIPE}="IGNORE"; my
$s=<STDIN>;unless (print $s) { die "error writing​: $!\n" }' | true
error writing​: Broken pipe

print $s or die $! => 32
unless (print $s) { die $! } => Broken pipe

Best regards,

Bram

@p5pRT
Copy link
Author

p5pRT commented Nov 3, 2009

From Mark.Martinec@ijs.si

$ date | perl -T -e '$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

Btw, this is still the case with 5.10.1.

  Mark

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2009

From jim@meyering.net

Mark Martinec wrote​:

$ date | perl -T -e '$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

Btw, this is still the case with 5.10.1.

If you untaint $s before printing it, you'll get the usual
strerror-style (not numeric) expansion of $!.

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2009

From jim@meyering.net

Mark Martinec wrote​:

$ date | perl -T -e '$|=1; $SIG{PIPE}="IGNORE"; my $s=<STDIN>;
print $s or die "error writing​: $!\n"' | true
error writing​: 32

Btw, this is still the case with 5.10.1.

Same for blead, built from git an hour or so ago​:

  This is perl 5, version 11, subversion 2 (v5.11.2-81-g162177c*) \
  built for x86_64-linux

Here's a slightly simpler demonstration​: with -T, we get only a number​:

  $ perl -Te '$!=20; warn "$0​: $!\n"'
  -e​: 20

without -T, we get the diagnostic we expect​:

  $ perl -le '$!=20; warn "$0​: $!\n"'
  -e​: Not a directory

Same results if I invoke it with an empty environment​:

  $ env -i perl -Te '$!=20; warn "$0​: $!\n"'
  -e​: 20

or with an explicit LC_ALL=C​:

  $ env -i LC_ALL=C perl -Te '$!=20; warn "$0​: $!\n"'
  -e​: 20

Here's one work-around​: pull the tainted $0 out of the double quotes​:

  $ perl -Te '$!=20; warn $0."​: $!\n"'
  -e​: Not a directory

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2010

From @iabyn

Now fixed in blead (hopefully) by the following commit​:

commit 516602a35e0eaac5574157357adc8e72978da5db
Author​: David Mitchell <davem@​iabyn.com>
AuthorDate​: Mon Jan 11 21​:42​:07 2010 +0000
Commit​: David Mitchell <davem@​iabyn.com>
CommitDate​: Mon Jan 11 21​:46​:45 2010 +0000

  fix for [perl #61976] Errno ($!) not evaluated to a error message string
  (5.10.0 in taint mode)
 
  Change 27176 / 2a509ed fixed a taint
  bug, which as a side effect, meant that $! used within a tainted
expression
  failed to have a string value.
 
  This quick fix just makes sure the POK flag is set (prior to it being
  shifted back to pPOK).

Affected files ...
 
  M mg.c
  M t/op/taint.t

Differences ...

Inline Patch
diff --git a/mg.c b/mg.c
index fb91325..ddfc2ff 100644
--- a/mg.c
+++ b/mg.c
@@ -1048,6 +1048,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
 	else
 #endif
 	sv_setpv(sv, errno ? Strerror(errno) : "");
+	SvPOK_on(sv);	/* may have got removed during taint processing */
 	RESTORE_ERRNO;
 	}
 #endif
diff --git a/t/op/taint.t b/t/op/taint.t
index 796b6fa..161073d 100644
--- a/t/op/taint.t
+++ b/t/op/taint.t
@@ -17,7 +17,7 @@ use Config;
 use File::Spec::Functions;
 
 BEGIN { require './test.pl'; }
-plan tests => 301;
+plan tests => 302;
 
 $| = 1;
 
@@ -1308,6 +1308,17 @@ foreach my $ord (78, 163, 256) {
     ok(tainted($zz), "pack a*a* preserves tainting");
 }
 
+# Bug RT #61976 tainted $! would show numeric rather than string value
+
+{
+    my $tainted_path = substr($^X,0,0) . "/no/such/file";
+    my $err;
+    # $! is used in a tainted expression, so gets tainted
+    open my $fh, $tainted_path or $err= "$!";
+    unlike($err, qr/^\d+$/, 'tainted $!');
+}
+
+
 # This may bomb out with the alarm signal so keep it last
 SKIP: {
     skip "No alarm()"  unless $Config{d_alarm};

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2010

@iabyn - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Jan 11, 2010
@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2010

From @iabyn

Correction​: the commit was 0097b43
(I keep forgetting to git push!)

@p5pRT
Copy link
Author

p5pRT commented Apr 26, 2013

From @JensTimmerman

I am still seeing this problem when compiling Perl with icc (intel
compiler)

I can reproduce this with every versions of icc (2011.1.107, 2011.4.191,
2011.10.319, 2011.13.367) , and every version of perl (5.12.2, 5.12.3,
5.14.2, 5.16.3) I tried.

Latest test was
Perl 5.16.3 compiled with icc 2011.13.367

The only tests that fail after the build are the testcase in this ticket
+ the one in dist/constant/t/constant.t
cmp_ok length(E2BIG), '>', 6;
which is triggered by the same problem.

-bash-3.2$ perl -Te '$!=20; warn "$0​: $!\n"'
-e​: 20
-bash-3.2$ perl -e '$!=20; warn "$0​: $!\n"'
-e​: 20
-bash-3.2$ perl -le '$!=20; warn "$0​: $!\n"'
-e​: 20
-bash-3.2$ perl -Te '$!=20; warn $0."​: $!\n"'
-e​: 20

Perl built with gcc on the same system works as expected.

@p5pRT
Copy link
Author

p5pRT commented May 1, 2013

@iabyn - Status changed from 'resolved' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @khwilliamson

The status of this wasn't clear to me until I did some experimentation.
The bug appears to be fixed under gcc; but apparently is sill broken
with the icc compiler.

--
Karl Williamson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant