[32609] in Perl-Users-Digest
Perl-Users Digest, Issue: 3882 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Sun Feb 17 11:09:42 2013
Date: Sun, 17 Feb 2013 08:09:07 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Sun, 17 Feb 2013 Volume: 11 Number: 3882
Today's topics:
Re: Apache 2.2 & Perl CGI::Simple running under separat <ben@morrow.me.uk>
Re: Apache 2.2 & Perl CGI::Simple running under separat <rweikusat@mssgmbh.com>
Re: Apache 2.2 & Perl CGI::Simple running under separat <rweikusat@mssgmbh.com>
Re: Apache 2.2 & Perl CGI::Simple running under separat <ben@morrow.me.uk>
Re: Apache 2.2 & Perl CGI::Simple running under separat <hjp-usenet2@hjp.at>
Re: Apache 2.2 & Perl CGI::Simple running under separat <ben@morrow.me.uk>
Re: assignments of arrays <derykus@gmail.com>
Re: assignments of arrays <ben@morrow.me.uk>
Re: assignments of arrays <toralf.foerster@gmx.de>
Re: assignments of arrays <hjp-usenet2@hjp.at>
Re: assignments of arrays (Seymour J.)
Re: Is there a shorter, more elegant way to write this <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Is there a shorter, more elegant way to write this deep <ignoramus329@NOSPAM.329.invalid>
Re: Is there a shorter, more elegant way to write this <ben@morrow.me.uk>
Re: Is there a shorter, more elegant way to write this <rvtol+usenet@xs4all.nl>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Sun, 17 Feb 2013 04:33:40 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <4636v9-iep.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Ben Morrow <ben@morrow.me.uk> writes:
>
> > 'Starting as root, from a controlled environment, and permanently
> > switching down to an unprivileged uid before doing anything dangerous'
> > and 'running setid root from a potentially attacker-controlled
> > environment' are very different security situations. Making a CGI
> > program setid root is very stupid; doing so with a program *designed* to
> > be able to run arbitrary commands under arbitrary uids is just
> > insane.
>
> As Michael already wrote: There is no other option when something
> executed via CGI is supposed to perform some task the user the web
> server runs as cannot perform.
And as I explained, the *is* another option: have the webserver contact
another daemon already running as another user.
> Since there is no reason why the
> wrapper should do anything with any information in its runtime
> environment because its job is just to change to a specific user id
> and execute another file, it's exploitable surface ought to be
> non-existent.
>
> > What happens if there's an exploitable security hole in cgiwrap? (This
> > is a possibility you *must* consider. Any non-trivial piece of software
> > potentially contains exploitable security holes, and any piece of
> > software which changes uid is non-trivial.)
>
> 'Changing the UID' is a single system call. This is trivial.
Go and read a few CVEs until you begin to get an idea of some of the
ways uncontrolled execution environments can cause security problems.
If there was no risk here, you might as well just go ahead and make the
individual CGIs setuid. (If they're in Perl you'll have to disable the
kernel's no-setid-scripts feature, but never mind, there's no risk,
right?)
> > You've just given an attacker root over the network. What if *any*
> > other process on the machine is compromised? You've just given them
> > a way to elevate that to a root compromise.
>
> That's all nice and dandy but since the "dangerous situation" can't be
> avoided for technical reasons, there is no other choice but "try to
> get it right" (I have no idea how the cgiwrap code looks like but
> unless you can point at an actual problem with it, this is an entirely
> theoretic discussion hanging in the air).
>
<snip>
> > You should run any process which talks directly to the network under a
> > unique uid, and as far as possible move all actual work out to other
> > processes under other uids. You should assume any process which talks
> > directly to the network is liable to be completely compromised, and
> > restrict its access to the rest of the system accordingly.
>
> I don't think I should perform all kinds of 'configuration voodoo' in the
> hope that it will keep me safe from nebulous "unknown dangers",
> especially if this configuration voodoo involves running a lot of
> complicated code which may well have its own 'exploitable
> errors'. Bugs which are discovered need to be fixed and the only way
> to be 'safe' from 'yet unknown future dangers' is 'immediate suicide'.
You obviously have as little understanding of secure programming and
defence-in-depth as you do of modularity and maintainable programming.
For everyone's sake, I hope you are not responsible for any code which
is exposed to the Internet.
Ben
------------------------------
Date: Sun, 17 Feb 2013 14:03:23 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <87zjz3ujf8.fsf@sapphire.mobileactivedefense.com>
Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> Ben Morrow <ben@morrow.me.uk> writes:
[...]
>> I don't think I should perform all kinds of 'configuration voodoo' in the
>> hope that it will keep me safe from nebulous "unknown dangers",
>> especially if this configuration voodoo involves running a lot of
>> complicated code which may well have its own 'exploitable
>> errors'. Bugs which are discovered need to be fixed and the only way
>> to be 'safe' from 'yet unknown future dangers' is 'immediate suicide'.
>
> You obviously have as little understanding of secure programming and
> defence-in-depth as you do of modularity and maintainable
> programming.
This kind of aggressive name-calling instead of argueing, especially
considering that it is based on nothing because you certainly haven't
seen any non-trivial piece of code I wrote in the last seven years or
so, is really surreptitious. But well, so be it: My idea of
'modularity' is based on using modules in order to structure code into
conceptually related subsets communicating with each other using
defined interfaces. I can only guess what your idea of 'modularity'
is but I figure it must be something close [blindly] downloading
enormously sized globs of code you don't really know and most of which
you don't need because the globs are named 'modules'. This translates
to 'having no idea of modularity' in my universe and that you're seem
unaware of the problems which can be caused by relying on insanely
large amounts of code written by 'random people on the internet' in
order to accomplish even the most trivial tasks strongly suggests that
your idea of 'maintaining code' is "Thank God, I don't have do
that!". That you further seem to believe that everything which is just
complicated enough must have been created with the help of some kind
of 'magic wand' which had caused it to be free of 'possible
exploitable errors' while you seem convinced that everything which is
simple must be full of them means your understanding of 'how to write
code without "unintended features" must be pretty much close to zero.
------------------------------
Date: Sun, 17 Feb 2013 14:17:12 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <87bobjnhxz.fsf@sapphire.mobileactivedefense.com>
Rainer Weikusat <rweikusat@mssgmbh.com> writes:
[...]
> This kind of
[...]
An addition that: This was a totally useless text because "conjectures
about you I can come up with based on posting you wrote I've read"
rest on at least as shaky foundations as "conjectures about me you can
come up with based on ..." and - even assuming some or all of them
were true - neither of both matter because of their content and
they're certainly unrelated to both the topic of the thread and the
newsgroup.
------------------------------
Date: Sun, 17 Feb 2013 15:21:23 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <j497v9-au01.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>
> (I have no idea how the cgiwrap code looks like but
> unless you can point at an actual problem with it, this is an entirely
> theoretic discussion hanging in the air).
Since you asked: once it has located the script it is supposed to be
executing (using an algorithm with rather more ambiguity in it than I
would be entirely happy with), it stats it and then does various
security checks on the result, to determine if the user it will use is
allowed to execute this script. These checks are *entirely* pointless,
since the next thing it does is pass the script name to execve. (This
race condition is exactly why setid scripts were disabled in the kernel
in the first place.) It doesn't even bother to check the directory it's
in isn't writable, and there are no warnings in the documentation about
this.
It took me about five minutes to find that, mostly because I was
expecting it to be there.
Ben
------------------------------
Date: Sun, 17 Feb 2013 15:30:53 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <slrnki1qct.ktp.hjp-usenet2@hrunkner.hjp.at>
On 2013-02-17 04:33, Ben Morrow <ben@morrow.me.uk> wrote:
>
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> Ben Morrow <ben@morrow.me.uk> writes:
>>
>> > 'Starting as root, from a controlled environment, and permanently
>> > switching down to an unprivileged uid before doing anything dangerous'
>> > and 'running setid root from a potentially attacker-controlled
>> > environment' are very different security situations. Making a CGI
>> > program setid root is very stupid; doing so with a program *designed* to
>> > be able to run arbitrary commands under arbitrary uids is just
>> > insane.
>>
>> As Michael already wrote: There is no other option when something
>> executed via CGI is supposed to perform some task the user the web
>> server runs as cannot perform.
>
> And as I explained, the *is* another option: have the webserver contact
> another daemon already running as another user.
I agree fully that this is usually the best solution from a security POV
and sometimes for other reasons as well. I have recommended FastCGI and
HTTP Proxy solutions here and elsewhere in the past and I will continue
to do so.
But ...
>> Since there is no reason why the wrapper should do anything with any
>> information in its runtime environment because its job is just to
>> change to a specific user id and execute another file, it's
>> exploitable surface ought to be non-existent.
>>
>> > What happens if there's an exploitable security hole in cgiwrap? (This
>> > is a possibility you *must* consider. Any non-trivial piece of software
>> > potentially contains exploitable security holes, and any piece of
>> > software which changes uid is non-trivial.)
>>
>> 'Changing the UID' is a single system call. This is trivial.
>
> Go and read a few CVEs until you begin to get an idea of some of the
> ways uncontrolled execution environments can cause security problems.
>
> If there was no risk here, you might as well just go ahead and make the
> individual CGIs setuid. (If they're in Perl you'll have to disable the
> kernel's no-setid-scripts feature, but never mind, there's no risk,
> right?)
... I think this is rhetorical hyperbole and would like to get back to a
rational assessment of risks here:
A setuid wrapper for CGI scripts like suexec or (presumably) cgiwrap
does not run in an uncontrolled execution environment. It is designed to
be called with a strictly defined environment from a web server, and it
can (and usually does) take steps to ensure that this is the case.
Furthermore, such wrappers can (and do) sanitize the environment for the
scripts they call.
Of course that makes them non-trivial in Rainer's sense: It is just
patently untrue that
>> there is no reason why the wrapper should do anything with any
>> information in its runtime environment because its job is just to
>> change to a specific user id and execute another file
A well-designed general purpose wrapper has to do a lot more than that
and that extra complexity may make the wrapper itself exploitable (lack
of that complexity may make it easy to trick the wrapper into executing
an arbitrary program and/or attack the CGI program).
A CGI script/program OTOH usually doesn't expect to be called in a
hostile environment and takes no steps to prevent that. Making such a
script setuid is extremely dangerous because the author didn't expect it
and probably had no idea how to write a secure setuid program anyway.
Depending on who can set the setuid bit (and for whom) it also depends
on how much you trust the authors of the CGI programs on your system.
But that's also true for wrappers and even separate servers, although to
a lesser extent.
An external server is also not risk-free. For example, if it listens on
a Unix socket, who can access that socket and feed it malformed
requests? Even worse if it listens on a network socket.
These points are horribly incomplete. I could easily write a 20 page
paper on the subject and maybe even a book - so I'm just mentioning a
few aspects to think about.
But to sum it up, for me there is a rough order of risk from most to
least risky:
* Monolithic server which runs everything.
* External setuid programs
* External programs via wrapper
* External server which can be accessed only through a defined
protocol.
But this is very rough and I am prepared to reevaluate this on a case by
case basis. In some cases it may be that the monolithic server really is
the most secure option (usually if it is small and special-purpose) or
that the external server is the worst (if it is big and complex and
buggy and there is no reliable way to restrict access).
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
------------------------------
Date: Sun, 17 Feb 2013 15:59:45 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Apache 2.2 & Perl CGI::Simple running under separate uid's: SCGI? FCGI? PSGI?
Message-Id: <hcb7v9-u711.ln1@anubis.morrow.me.uk>
Quoth "Peter J. Holzer" <hjp-usenet2@hjp.at>:
> On 2013-02-17 04:33, Ben Morrow <ben@morrow.me.uk> wrote:
> > Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> >>
> >> 'Changing the UID' is a single system call. This is trivial.
> >
> > Go and read a few CVEs until you begin to get an idea of some of the
> > ways uncontrolled execution environments can cause security problems.
> >
> > If there was no risk here, you might as well just go ahead and make the
> > individual CGIs setuid. (If they're in Perl you'll have to disable the
> > kernel's no-setid-scripts feature, but never mind, there's no risk,
> > right?)
>
> ... I think this is rhetorical hyperbole and would like to get back to a
> rational assessment of risks here:
OK :).
> A setuid wrapper for CGI scripts like suexec or (presumably) cgiwrap
> does not run in an uncontrolled execution environment. It is designed to
> be called with a strictly defined environment from a web server, and it
> can (and usually does) take steps to ensure that this is the case.
>
> Furthermore, such wrappers can (and do) sanitize the environment for the
> scripts they call.
It may not be *designed to* run in an uncontrolled environment; that
does not imply it *does not*.
The piece of cgiwrap documentation I originally quoted said
chmod 1755 cgiwrap
cgiwrap makes a token attempt to clean a few environment variables but
doesn't clear the environment completely (and allows the program it
execs to inherit its environment). That means that any user can set
PERL5LIB to something appropriate and execute arbitrary code as any
other user with a Perl cgi accessible to cgiwrap.
I realise this is just a bug in cgiwrap, but this sort of mistake is
incredibly easy to make. Operating systems and applications keep adding
new and exciting ways for the environment (and I don't just mean
environ(7), I mean the whole execution environment) to affect the way a
program behaves, so any program which starts setuid root and then tries
to clean things up ends up playing a dangerous game of catch-up.
> An external server is also not risk-free. For example, if it listens on
> a Unix socket, who can access that socket and feed it malformed
> requests? Even worse if it listens on a network socket.
This is of course true, and very important. However backend protocols
like this usually have to pass some sort of authentication (permissions
on a Unix socket, SSL or Kerberos or something over the network) before
the server even starts trying to interpret the protocol data. This makes
it a good deal harder to mount an attack (unless you attack the
authentication protocol, of course, but that should be a trusted
implementation of a standard protocol).
Ben
------------------------------
Date: Sat, 16 Feb 2013 13:26:06 -0800 (PST)
From: "C.DeRykus" <derykus@gmail.com>
Subject: Re: assignments of arrays
Message-Id: <860b85d9-fb79-4924-a75c-e23cd91d599b@googlegroups.com>
On Friday, February 15, 2013 2:57:16 PM UTC-8, Ben Morrow wrote:
> Quoth "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>:
>
> > ...
>
> An easier way to do this is to use the Clone module:
>
>
>
> use Clone "clone";
>
>
>
> my @Values = map clone($_), @Zero;
>
> # or
>
> my @Values = @{ clone \@Zero };
>
Alternatively: Storable's dclone:
use Storable qw/dclone/;
@Values = @{ dclone \@Zero };
Storable is core which is a plus but I notice the docs mention:
"Clone is faster for data structures with 3 or less levels,
while dclone() can be faster for structures 4 or more levels deep."
--
Charles DeRykus
------------------------------
Date: Sat, 16 Feb 2013 23:37:19 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: assignments of arrays
Message-Id: <fqh5v9-83k.ln1@anubis.morrow.me.uk>
Quoth "C.DeRykus" <derykus@gmail.com>:
>
> Storable is core which is a plus but I notice the docs mention:
>
> "Clone is faster for data structures with 3 or less levels,
> while dclone() can be faster for structures 4 or more levels deep."
Interesting... last time I read the Storable docs that note said Clone
was always faster. I suppose this must be some sort of CPU-cache
thrashing effect, where once you get to the point where the data
structure won't fit into cache it's actually quicker to serialise it and
then deserialise it again.
Ben
------------------------------
Date: Sun, 17 Feb 2013 09:16:49 +0100
From: =?UTF-8?B?VG9yYWxmIEbDtnJzdGVy?= <toralf.foerster@gmx.de>
Subject: Re: assignments of arrays
Message-Id: <kfq3k0$har$1@dont-email.me>
On 02/15/2013 08:07 PM, George Mpouras wrote:
> At your statement my @Values = @Zero;
> you are "playing" with array references.
OTOH this was so clear for me b/c if I pass parameters to a sub like foo
(@Values) then this means a call-by-value whereas foo (\@Values) passes
just the reference to the sub called "foo".
--
MfG/Sincerely
Toralf Förster
pgp finger print: 7B1A 07F4 EC82 0F90 D4C2 8936 872A E508 7DB6 9DA3
------------------------------
Date: Sun, 17 Feb 2013 15:41:45 +0100
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: assignments of arrays
Message-Id: <slrnki1r19.ktp.hjp-usenet2@hrunkner.hjp.at>
On 2013-02-17 08:16, Toralf Förster <toralf.foerster@gmx.de> wrote:
> On 02/15/2013 08:07 PM, George Mpouras wrote:
>> At your statement my @Values = @Zero;
>> you are "playing" with array references.
>
> OTOH this was so clear for me b/c if I pass parameters to a sub like foo
> (@Values) then this means a call-by-value
No.
Parameters are passed by reference in Perl.
For example, consider this code:
sub foo {
$_[1] = 5;
}
my @x = (1, 2, 3);
foo(@x);
print "@x\n";
my ($x, $y, $z) = qw(a b c);
foo($x, $y, $z);
print "$x $y $z\n";
__END__
It prints
1 5 3
a 5 c
which clearly shows that the array @x and the variably $y were passed by
reference (in Perl jargon, we call this "aliasing", but it's the same
concept).
What creates the *illusion* that Perl function calls are by value is the
convention to immediately assign parameters to local variables. So you
would normally write foo as
sub foo {
my @p = @_;
$p[1] = 5;
}
or
sub foo {
my ($p1, $p2, $p3) = @_;
$p2 = 5;
}
Here the assignments in the second line alter only the local variable
(@p or $p2, respectively), not the parameters. But it's the assignment
in the first line which causes the values to be copied, not the function
call.
hp
--
_ | Peter J. Holzer | Fluch der elektronischen Textverarbeitung:
|_|_) | Sysadmin WSR | Man feilt solange an seinen Text um, bis
| | | hjp@hjp.at | die Satzbestandteile des Satzes nicht mehr
__/ | http://www.hjp.at/ | zusammenpaßt. -- Ralph Babel
------------------------------
Date: Sun, 17 Feb 2013 10:26:07 -0500
From: Shmuel (Seymour J.) Metz <spamtrap@library.lspace.org.invalid>
Subject: Re: assignments of arrays
Message-Id: <511ea568$69$fuzhry+tra$mr2ice@news.patriot.net>
In <kflt3j$sqj$1@dont-email.me>, on 02/15/2013
at 07:01 PM, Toralf Förster <toralf.foerster@gmx.de> said:
>In the following program I'd expect that line 29 fills @Values with
>zeros, but for i==2 this is counterproofed.
Perl doesn't have two-dimensional arrays; in your case, you have a
one-dimensional array of references. Line 29 fills @Values with
references to arrays filled with zeros the first time around, vecause
lines 20-24 had previously filled @Zero with references to arrays
filled with zeros. Line 41 alters the arrays that both @Values and
@Zero refer to, so $Zero[$r] no lomger refers to an array of zeros.
> 41 $Values[$r][$c] = 1;
At this point $Values[$r] and $Zero[$r] contain the same reference, so
you are also changing the value of $Zero[$r][$c].
--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>
Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to spamtrap@library.lspace.org
------------------------------
Date: Sun, 17 Feb 2013 14:07:45 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: Is there a shorter, more elegant way to write this deep hash lookup statement
Message-Id: <kfqh6j$2nnu$1@news.ntua.gr>
use strict;
use warnings;
my $ebay_record = {};
my $is_freight = 1;
$ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService22}
= 1;
if (( exists
$ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
) && (
$ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
== $is_freight ))
{
print "ok\n";
}
------------------------------
Date: Sat, 16 Feb 2013 18:16:33 -0600
From: Ignoramus329 <ignoramus329@NOSPAM.329.invalid>
Subject: Is there a shorter, more elegant way to write this deep hash lookup statement
Message-Id: <9ICdnTbYXpf8vL3MnZ2dnUVZ_oSdnZ2d@giganews.com>
As I always say 'use strict; use warnings', I have this statement in my program:
$is_freight = 1
if $ebay_record
&& $ebay_record->{ShippingDetails}
&& $ebay_record->{ShippingDetails}->{ShippingServiceOptions}
&& $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
&& $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService} eq 'Freight';
This is a correct statement and it does not give errors or warnings,
however, I would like to know if I can write it in a shorter way.
Any suggestions?
Thanks
------------------------------
Date: Sun, 17 Feb 2013 00:44:51 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Is there a shorter, more elegant way to write this deep hash lookup statement
Message-Id: <3pl5v9-nik.ln1@anubis.morrow.me.uk>
Quoth Ignoramus329 <ignoramus329@NOSPAM.329.invalid>:
> As I always say 'use strict; use warnings', I have this statement in
> my program:
>
> $is_freight = 1
> if $ebay_record
> && $ebay_record->{ShippingDetails}
> && $ebay_record->{ShippingDetails}->{ShippingServiceOptions}
> &&
> $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
> &&
> $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
> eq 'Freight';
>
> This is a correct statement and it does not give errors or warnings,
> however, I would like to know if I can write it in a shorter way.
my $r = $ebay_record;
$r &&= $r->{"Shipping$_"} for
qw/ Details ServiceOptions Service /;
$is_freight = 1 if $r && $r eq 'Freight';
Ben
------------------------------
Date: Sun, 17 Feb 2013 12:18:47 +0100
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: Is there a shorter, more elegant way to write this deep hash lookup statement
Message-Id: <5120bc97$0$6894$e4fe514c@news2.news.xs4all.nl>
On 2013-02-17 01:16, Ignoramus329 wrote:
> As I always say 'use strict; use warnings', I have this statement in my program:
>
> $is_freight = 1
> if $ebay_record
> && $ebay_record->{ShippingDetails}
> && $ebay_record->{ShippingDetails}->{ShippingServiceOptions}
> && $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService}
> && $ebay_record->{ShippingDetails}->{ShippingServiceOptions}->{ShippingService} eq 'Freight';
>
> This is a correct statement and it does not give errors or warnings,
> however, I would like to know if I can write it in a shorter way.
That kind of code smells. If you really need such a convoluted
structure, and are also worried about autovivication (both of which
probably come from the same basic issue), then what keeps you from
creating a sub for it? Call it deep_exists() or so.
You could make it return the hashref or undef, a bit like can().
Or wait for the &-> operator:
$is_freight =
$ebay_row&->{ShippingDetails}&->{ShippingServiceOptions}&->{ShippingService}
eq 'Freight';
(with the wild assumption that the shortcutting will even disarm the 'eq')
--
Ruud
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 3882
***************************************