Most code which attempts to find the version number of a given module either uses a naive regex, uses "eval" on the version line, or loads the module and calls $module->VERSION.
I'm writing Module::SafeVersion which attempts to do this correctly, but it may never get released. I'm employing a combination approach of using a rather complicated regex along with some "cleanup" code to handle the majority of cases. Currently it properly extracts about 98% of the versions of modules installed on my laptop. However, the special cases are significant and I can't ignore them.
I can try to continually expand the regex and the cleanup code, but I'm sadly beginning to think that what needs to be done is to build in special cases for those modules which have jumped through ridiculous hoops to generate their version numbers. Let's look at some examples:
# From SOAP::Lite
$VERSION = sprintf("%d.%s", map {s/_//g; $_} q$Name: release-0_60-public $ =~ /-(\d+)_([\d_]+)/)
# From SQL::Abstract
$VERSION = do { my @r=(q$Revision: 1.20 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
# From CPAN
my $VERSION = sprintf "%.2f", substr(q$Rev: 245 $,4)/100;
(It should also be pointed out that there are plenty of problems with this approach, too. Particulary since it will never be 100% successful).
Schwern argued that this entire module is the wrong approach. Specifically, if eval'ing a version string is a problem, this implies that you already have bad code on your box and the version string is the least of your problems. PAUSE apparently runs in a chroot jail, so the only folks likely to be bitten by a version string attack would be smoke testers. Thus, if I have code on my box, it should automatically be viewed as trusted. Thoughts?
Cheers,
Ovid
New address of my CGI Course.
Sounds like smoke testers should be running their smoking in a chroot jail, too. Maybe chroot jails need to be easier to set up ...
Linking revision data into version is extremely common, and very convenient practice. Id say you should support such versions.
I do have a fair amount of code in place to allow them since it's so common. Unfortunately, as you can see from the examples above, trying to reliably parse such information is extremely difficult and in many cases, it's not worth the trouble. Hence my thoughts on special casing some modules. It's the only way I can do that reliably.
Cheers,
Ovid
New address of my CGI Course.
Heres one I use regularly:
($VERSION) = sprintf "%d.%03d", 0, ' $Revision:: 6 $' =~ /::\s+(\S+)/; #
Im not convinced that there is a security issue here to be honest. I think im with Schwern on this. If there is a security issue with version evaluation you already have serious problems. I mean presumably they could have just set up the Makefile.pl to nuke your system.....
Your premise appears to be that loading the module in order to obtain it's $VERSION is inherently unsafe; and you are attempting to reimplement some subset of the perl parser in order to avoid that "risk"; but if your module library is compromised enough that the risk of loading the modules it contains is real, how are you going to cater for the risk that your module is the one that has been compromised?
Further, what is the point in determining a module's $VERSION safely, when to use that module, you will need to load it? At which point it's version would be available to you, but you would of course have exposed yourself to the risk of it's being evaluated.
The only useful, non-paranoia uses I can see for this, would be: a) scanning the entire installed library and obtaining the versions of all the modules without ending up with them all loaded in your process; or b) risking 'collisions' between modules by loading them all simultaneously; but that would more easily be done by spawning one-liners that load the modules and print their $VERSION thereby isolating each from the next.
my @allmodules = map{ ... } @INC;
...
for my $module ( @allmodules ) {
print "$module :", `perl -M$module le"\$${module}::VERSION"`;
}
I agree with Schwern.
perlmonks.org content © perlmonks.org and BrowserUk, demerphq, dragonchild, itub, Ovid
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03