Skip to content

Commit 42ee410

Browse files
committed
Merge pull request #14 from perl5-dbi/dbd_file-nodir
DBD-File prevent non-existing folder in f_dir on connect RT 99508
2 parents 06787b3 + 222f720 commit 42ee410

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

Changes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ DBI::Changes - List of significant changes to the DBI
1616
Fixed DBI::DBD::SqlEngine to complain loudly when prerequite
1717
driver_prefix is not fulfilled (RT#93204) [Jens Rehsack]
1818
Fixed redundant sprintf argument warning RT#97062 [Reini Urban]
19+
Fixed security issue where DBD::File drivers would open files
20+
from folders other than specifically passed using the
21+
f_dir attribute RT#99508 [H.Merijn Brand]
1922

2023
Changed delete $h->{$key} to work for keys with 'private_' prefix
2124
per request in RT#83156. local $h->{$key} works as before.

lib/DBD/File.pm

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use base qw( DBI::DBD::SqlEngine );
3535
use Carp;
3636
use vars qw( @ISA $VERSION $drh );
3737

38-
$VERSION = "0.42";
38+
$VERSION = "0.43";
3939

4040
$drh = undef; # holds driver handle(s) once initialized
4141

@@ -85,6 +85,8 @@ use warnings;
8585

8686
use vars qw( @ISA $imp_data_size );
8787

88+
use Carp;
89+
8890
@DBD::File::dr::ISA = qw( DBI::DBD::SqlEngine::dr );
8991
$DBD::File::dr::imp_data_size = 0;
9092

@@ -100,6 +102,31 @@ sub dsn_quote
100102
# XXX rewrite using TableConfig ...
101103
sub default_table_source { "DBD::File::TableSource::FileSystem" }
102104

105+
sub connect
106+
{
107+
my ($drh, $dbname, $user, $auth, $attr) = @_;
108+
109+
# We do not (yet) care about conflicting attributes here
110+
# my $dbh = DBI->connect ("dbi:CSV:f_dir=test", undef, undef, { f_dir => "text" });
111+
# will test here that both test and text should exist
112+
if (my $attr_hash = (DBI->parse_dsn ($dbname))[3]) {
113+
if (defined $attr_hash->{f_dir} && ! -d $attr_hash->{f_dir}) {
114+
my $msg = "No such directory '$attr_hash->{f_dir}";
115+
$drh->set_err (2, $msg);
116+
$attr_hash->{RaiseError} and croak $msg;
117+
return;
118+
}
119+
}
120+
if ($attr and defined $attr->{f_dir} && ! -d $attr->{f_dir}) {
121+
my $msg = "No such directory '$attr->{f_dir}";
122+
$drh->set_err (2, $msg);
123+
$attr->{RaiseError} and croak $msg;
124+
return;
125+
}
126+
127+
return $drh->SUPER::connect ($dbname, $user, $auth, $attr);
128+
} # connect
129+
103130
sub disconnect_all
104131
{
105132
} # disconnect_all
@@ -130,7 +157,7 @@ sub data_sources
130157
{
131158
my ($dbh, $attr, @other) = @_;
132159
ref ($attr) eq "HASH" or $attr = {};
133-
exists $attr->{f_dir} or $attr->{f_dir} = $dbh->{f_dir};
160+
exists $attr->{f_dir} or $attr->{f_dir} = $dbh->{f_dir};
134161
exists $attr->{f_dir_search} or $attr->{f_dir_search} = $dbh->{f_dir_search};
135162
return $dbh->SUPER::data_sources ($attr, @other);
136163
} # data_source
@@ -343,6 +370,10 @@ sub data_sources
343370
? $attr->{f_dir}
344371
: File::Spec->curdir ();
345372
defined $dir or return; # Stream-based databases do not have f_dir
373+
unless (-d $dir && -r $dir && -x $dir) {
374+
$drh->set_err ($DBI::stderr, "Cannot use directory $dir from f_dir");
375+
return;
376+
}
346377
my %attrs;
347378
$attr and %attrs = %$attr;
348379
delete $attrs{f_dir};

t/49dbd_file.t

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,31 @@ ok ($dbh = DBI->connect ("dbi:File:", undef, undef, {
207207
ok ($dbh->do ("drop table $tbl"), "table drop");
208208
is (-s $tbl_file, undef, "Test table removed"); # -s => size test
209209

210+
# ==================== Nonexisting top-dir ========================
211+
my %drh = DBI->installed_drivers;
212+
my $qer = qr{\bNo such directory};
213+
foreach my $tld ("./non-existing", "nonexisting_folder", "/Fr-dle/hurd0k/ok$$") {
214+
is (DBI->connect ("dbi:File:", undef, undef, {
215+
f_dir => $tld,
216+
217+
RaiseError => 0,
218+
PrintError => 0,
219+
}), undef, "Should not be able to open a DB to $tld");
220+
like ($DBI::errstr, $qer, "Error message");
221+
$drh{File}->set_err (undef, "");
222+
is ($DBI::errstr, undef, "Cleared error");
223+
my $dbh;
224+
eval { $dbh = DBI->connect ("dbi:File:", undef, undef, {
225+
f_dir => $tld,
226+
227+
RaiseError => 1,
228+
PrintError => 0,
229+
})};
230+
is ($dbh, undef, "connect () should die on $tld with RaiseError");
231+
like ($@, $qer, "croak message");
232+
like ($DBI::errstr, $qer, "Error message");
233+
}
234+
210235
done_testing ();
211236

212237
sub DBD::File::Table::fetch_row ($$)

0 commit comments

Comments
 (0)