Re: [bug-Class-DBI@xx.xxxx.xxx: [cpan #6434] LiveObject caching may return results from other DBs when using custom db_Main]

[prev] [thread] [next] [Date index for 2004/05/28]

From: Tim Bunce
Subject: Re: [bug-Class-DBI@xx.xxxx.xxx: [cpan #6434] LiveObject caching may return results from other DBs when using custom db_Main]
Date: 09:26 on 28 May 2004
On Fri, May 28, 2004 at 06:48:46AM +0100, Tony Bowden wrote:
> 
> My mod_perl2 application uses a custom db_Main method to connect to a database based on some information in the URL.  The app may be called with, say, db=STORE_1 or db=STORE_2.
> 
> The %Live_Objects caching introduced in CDB 0.96 uses the class name and primary keys to identify cached objects but does not pay attention to which DB instance the object belongs.
> 
> Problem: In a persisted environment (mod_perl), if I retrieve an object with ID 123 from the STORE_1 database, it will be cached and subsequent queries for object with ID 123 in the STORE_2 database (or any other database accessed with this class) will return the cached object.  This is incorrect behavior and a potential SECURITY HOLE since users of STORE_2 may now see data from STORE_1 without authorization.
> 
> My Workaround: Use Class::CGI 0.95 which does not exhibit this problem.
> 
> Solution: You should incorporate the dbh returned by $class->db_Main as part of the key used in identifying LiveObjects.

Using "$dbh" would be wrong. Using $dbh->{Name} would be better.
But even then there's a risk that multiple connections may use the
same DSN but different usernames (and thus different default schemas).
And even then there's a chance that connect() attributes may have a
significant influence on the connection.

I suggest moving the code that creates the $obj_key out into a
separate method that can then be subclassed in any way the application
may need. Document the issue alongside db_Main docs.

Here's an untested patch that also addresses [cpan #6435]

Tim.

--- DBI.pm.orig Fri May 28 10:06:28 2004
+++ DBI.pm      Fri May 28 10:22:07 2004
@@ -509,19 +509,23 @@
 my %Live_Objects;
 my $Init_Count = 0;

+sub _live_object_key {
+       my ($class, $data) = @_;
+       my @primary_columns = $class->primary_columns;
+
+       # no key unless all PK columns are defined
+       return "" unless @primary_columns == grep defined, @{$data}{@primary_columns};
+
+       # create single unique key for this object
+       return join "\030", $class, map { $_ . "\032" . $data->{$_} }
+                       sort @primary_columns;
+}
+
 sub _init {
        my $class = shift;
        my $data = shift || {};
        my $obj;
-       my $obj_key = "";
-
-       my @primary_columns = $class->primary_columns;
-       if (@primary_columns == grep defined, @{$data}{@primary_columns}) {
-
-               # create single unique key for this object
-               $obj_key = join "|", $class, map { $_ . '=' . $data->{$_} }
-                       sort @primary_columns;
-       }
+       my $obj_key = $class->_live_object_key($data);

        unless (defined($obj = $Live_Objects{$obj_key})) {



Re: [bug-Class-DBI@xx.xxxx.xxx: [cpan #6434] LiveObject caching may return results from other DBs when using custom db_Main]
Tim Bunce 09:26 on 28 May 2004

Generated at 11:34 on 01 Dec 2004 by mariachi v0.52