Home > Archive > PERL Beginners > January 2008 > Can't understand this code snippet
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Can't understand this code snippet
|
|
| Bootleg86 Bootleg86 2008-01-18, 7:02 pm |
| Hi,
I can't for the life of me figure out what this is trying to do
$token = $$ ^ unpack "%L*", `ps -A | "./bin/gzip"
Just seems to be it's trying to generate some random number.
I only know it's trying to XOR the process ID.
What does this part do?
unpack "%L*", `ps -A | "./bin/gzip"
Thanks
| |
| Yitzle 2008-01-18, 7:02 pm |
| On 1/18/08, bootleg86 bootleg86 <bootleg86@gmail.com> wrote:
> Hi,
> I can't for the life of me figure out what this is trying to do
> $token = $$ ^ unpack "%L*", `ps -A | "./bin/gzip"
>
> Just seems to be it's trying to generate some random number.
> I only know it's trying to XOR the process ID.
>
> What does this part do?
> unpack "%L*", `ps -A | "./bin/gzip"
>
> Thanks
ps -A lists all the processes on a Unix machine.
gzip compesses its input
`ps -A | gzip` will compress the text that ps -A outputs.
I presume the zipped version of your system's processes would look
fairly random, as it got a bunch of random PIDs, times, names, etc
http://perldoc.perl.org/functions/unpack.html
> unpack does the reverse of pack: it takes a string and expands it out into a list of values.
"%L*" is a "template" for unpack, whatever that means.
From pack: "L An unsigned long value." I guess it expands the gzip'd
string into longs, giving you a list of random longs.
| |
| Jenda Krynicky 2008-01-18, 7:02 pm |
| From: yitzle <yitzle@users.sourceforge.net>
> On 1/18/08, bootleg86 bootleg86 <bootleg86@gmail.com> wrote:
>
> ps -A lists all the processes on a Unix machine.
> gzip compesses its input
> `ps -A | gzip` will compress the text that ps -A outputs.
> I presume the zipped version of your system's processes would look
> fairly random, as it got a bunch of random PIDs, times, names, etc
>
> http://perldoc.perl.org/functions/unpack.html
> "%L*" is a "template" for unpack, whatever that means.
> I guess it expands the gzip'd
> string into longs, giving you a list of random longs.
You forgot the %. It causes pack to compute a checksum out of those
long values instead of returning the values itself. So you get a
16bit checksum of a fairly random data and xor it with the process
id. a fairly insteresting way to obtain a random number.
Jenda
===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery
| |
| Tom Phoenix 2008-01-18, 7:02 pm |
| On Jan 18, 2008 7:45 AM, bootleg86 bootleg86 <bootleg86@gmail.com> wrote:
> I can't for the life of me figure out what this is trying to do
> $token = $$ ^ unpack "%L*", `ps -A | "./bin/gzip"
Well, it's not complete, for one thing. What comes next?
> Just seems to be it's trying to generate some random number.
> I only know it's trying to XOR the process ID.
You've got the right idea. It looks as if somebody thought this was a
good way to choose a number that would be hard for anybody to predict,
even somebody who had the source code to the program.
> What does this part do?
> unpack "%L*", `ps -A | "./bin/gzip"
The part on the right looks to be the start of a shell command in
backticks. ps -A runs the ps command; the -A option means "Display
information about other users' processes including those without
controlling terminals," according to my manpage. It's hard to predict
what processes all users will be running at any given time.
Presumably the rest of the line feeds the ps data through gzip, a
compression program. The author of the program may be of the
impression that this will help make things unpredictable, but gzip
uses a pretty straightforward algorithm. In any case, the output of
gzip is presumably eventually passed back to perl as the return value
of the command in backticks. (Is there yet another process after
gzip?)
The unpack function, when given a "%" template, gives a checksum of
the data instead of the data itself.
Finally, as you saw, that checksum is xored with the current process
ID. Since the default checksum is 16 bits wide and (on most systems)
the pid is also 16 bits wide, the result is 16 hard-to-predict bits.
(For consistency, this line's author should have used an "S" format
instead of an "L" format in the unpack, although it could conceivably
have been an intentional decision to discard half of the available
bits.)
If that were my program, running under any modern perl version, I'd
exploit the fact that Perl's random number generator can give you 16
hard-to-predict bits much more easily. This line should be a drop-in
equivalent that's just as good, from an unpredictability standpoint,
and significantly faster and more portable:
my $token = int rand 2**16;
Still, I wouldn't write it that way without seeing more about how
$token is used further down the code. It might be that you could (or
even should) use more bits than 16, if it's really important to make
your token unguessable. But you can't upgrade to 40 bits by simply
writing this:
my $token = int rand 2**40; # won't work
.... because rand only produces a few bits of randomness each time it
is called. If you want a token with more bits, you can do something
like this:
my $bits_of_randomness = 40;
my $token = '';
while (length($token) < ($bits_of_randomness/4)) {
$token .= unpack "H4", pack "S", int rand 2**16;
}
Of course, that may require changes to subsequent parts of the code
that expected $token to be an integer instead of a string, for
example.
Hope this helps!
--Tom Phoenix
Stonehenge Perl Training
| |
| Bootleg86 Bootleg86 2008-01-18, 7:02 pm |
| Thanks all!
I was wondering why the author didn't just call rand.
I checked the rest of the source and it's just used as a unique identifier.
So using rand would have been much easier.
> If that were my program, running under any modern perl version, I'd
> exploit the fact that Perl's random number generator can give you 16
> hard-to-predict bits much more easily. This line should be a drop-in
> equivalent that's just as good, from an unpredictability standpoint,
> and significantly faster and more portable:
>
> my $token = int rand 2**16;
>
> Still, I wouldn't write it that way without seeing more about how
> $token is used further down the code. It might be that you could (or
> even should) use more bits than 16, if it's really important to make
> your token unguessable. But you can't upgrade to 40 bits by simply
> writing this:
>
> my $token = int rand 2**40; # won't work
>
> ... because rand only produces a few bits of randomness each time it
> is called. If you want a token with more bits, you can do something
> like this:
>
> my $bits_of_randomness = 40;
> my $token = '';
> while (length($token) < ($bits_of_randomness/4)) {
> $token .= unpack "H4", pack "S", int rand 2**16;
> }
>
> Of course, that may require changes to subsequent parts of the code
> that expected $token to be an integer instead of a string, for
> example.
>
> Hope this helps!
>
> --Tom Phoenix
> Stonehenge Perl Training
>
|
|
|
|
|