The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 123
DBI.pm 1021
DBI.xs 722
META.json 23
META.yml 1415
Makefile.PL 01
lib/DBD/File.pm 233
lib/DBD/Gofer.pm 11
lib/DBD/Proxy.pm 28
lib/DBI/DBD/SqlEngine/HowTo.pod 29
lib/DBI/DBD/SqlEngine.pm 09
lib/DBI/Profile.pm 16
lib/DBI/ProxyServer.pm 07
lib/DBI/PurePerl.pm 313
t/06attrs.t 07
t/49dbd_file.t 025
t/70callbacks.t 010
17 files changed (This is a version diff) 45213
@@ -6,7 +6,29 @@ DBI::Changes - List of significant changes to the DBI
 
 =cut
 
-=head2 Changes in DBI 1.631
+=head2 Changes in DBI 1.632
+
+    Fixed risk of memory corruption with many arguments to methods
+        originally reported by OSCHWALD for Callbacks but may apply
+        to other functionality in DBI method dispatch RT#86744.
+    Fixed DBD::PurePerl to not set $sth->{Active} true by default
+        drivers are expected to set it true as needed.
+    Fixed DBI::DBD::SqlEngine to complain loudly when prerequite
+        driver_prefix is not fulfilled (RT#93204) [Jens Rehsack]
+    Fixed redundant sprintf argument warning RT#97062 [Reini Urban]
+    Fixed security issue where DBD::File drivers would open files
+        from folders other than specifically passed using the
+        f_dir attribute RT#99508 [H.Merijn Brand]
+
+    Changed delete $h->{$key} to work for keys with 'private_' prefix
+        per request in RT#83156. local $h->{$key} works as before.
+
+    Added security notice to DBD::Proxy and DBI::ProxyServer because they
+        use Storable which is insecure. Thanks to ppisar@redhat.com RT#90475
+    Added note to AutoInactiveDestroy docs strongly recommending that it
+        is enabled in all new code.
+
+=head2 Changes in DBI 1.631 - 20th Jan 2014
 
 NOTE: This release changes the handle passed to Callbacks from being an 'inner'
 handle to being an 'outer' handle. If you have code that makes use of Callbacks,
@@ -11,7 +11,7 @@ package DBI;
 require 5.008_001;
 
 BEGIN {
-our $XS_VERSION = our $VERSION = "1.631"; # ==> ALSO update the version in the pod text below!
+our $XS_VERSION = our $VERSION = "1.632"; # ==> ALSO update the version in the pod text below!
 $VERSION = eval $VERSION;
 }
 
@@ -113,6 +113,12 @@ personally. The I<dbi-users> mailing list has lots of experienced
 people who should be able to help you if you need it. If you do email
 Tim he is very likely to just forward it to the mailing list.
 
+=head3 IRC
+
+DBI IRC Channel: #dbi on irc.perl.org (L<irc://irc.perl.org/#dbi>)
+
+=for html <a href="http://chat.mibbit.com/#dbi@irc.perl.org">(click for instant chatroom login)</a>
+
 =head3 Online
 
 StackOverflow has a DBI tag L<http://stackoverflow.com/questions/tagged/dbi>
@@ -138,7 +144,7 @@ sure that your issue isn't related to the driver you're using.
 
 =head2 NOTES
 
-This is the DBI specification that corresponds to DBI version 1.631
+This is the DBI specification that corresponds to DBI version 1.632
 (see L<DBI::Changes> for details).
 
 The DBI is evolving at a steady pace, so it's good to check that
@@ -345,6 +351,7 @@ my $dbd_prefix_registry = {
   mvsftp_      => { class => 'DBD::MVS_FTPSQL',     },
   mysql_       => { class => 'DBD::mysql',          },
   mx_          => { class => 'DBD::Multiplex',      },
+  neo_         => { class => 'DBD::Neo4p',          },
   nullp_       => { class => 'DBD::NullP',          },
   odbc_        => { class => 'DBD::ODBC',           },
   ora_         => { class => 'DBD::Oracle',         },
@@ -404,6 +411,7 @@ my $keeperr = { O=>0x0004 };
 	'FIRSTKEY'	=> $keeperr,
 	'NEXTKEY'	=> $keeperr,
 	'STORE'		=> { O=>0x0418 | 0x4 },
+	'DELETE'	=> { O=>0x0404 },
 	can		=> { O=>0x0100 }, # special case, see dispatch
 	debug 	 	=> { U =>[1,2,'[$debug_level]'],	O=>0x0004 }, # old name for trace
 	dump_handle 	=> { U =>[1,3,'[$message [, $level]]'],	O=>0x0004 },
@@ -1888,7 +1896,7 @@ sub _new_sth {	# called by DBD::<drivername>::db::prepare)
 	my $fields = $sth->FETCH('NUM_OF_FIELDS') || 0;
 	if ($fields <= 0 && !$sth->{Active}) {
 	    return $sth->set_err($DBI::stderr, "Statement has no result columns to bind"
-		    ." (perhaps you need to successfully call execute first)");
+		    ." (perhaps you need to successfully call execute first, or again)");
 	}
 	# Backwards compatibility for old-style call with attribute hash
 	# ref as first arg. Skip arg if undef or a hash ref.
@@ -3682,8 +3690,8 @@ the destruction of inherited handles cause the corresponding handles in the
 parent process to cease working.
 
 Either the parent or the child process, but not both, should set
-C<InactiveDestroy> true on all their shared handles. Alternatively the
-L</AutoInactiveDestroy> can be set in the parent on connect.
+C<InactiveDestroy> true on all their shared handles. Alternatively, and
+preferably, the L</AutoInactiveDestroy> can be set in the parent on connect.
 
 To help tracing applications using fork the process id is shown in
 the trace log whenever a DBI or handle trace() method is called.
@@ -3696,12 +3704,15 @@ from the DBI's method dispatcher, e.g. >= 9.
 Type: boolean, inherited
 
 The L</InactiveDestroy> attribute, described above, needs to be explicitly set
-in the child process after a fork(). This is a problem if the code that performs
-the fork() is not under your control, perhaps in a third-party module.
-Use C<AutoInactiveDestroy> to get around this situation.
+in the child process after a fork(), on every active database and statement handle.
+This is a problem if the code that performs the fork() is not under your
+control, perhaps in a third-party module.  Use C<AutoInactiveDestroy> to get
+around this situation.
 
 If set true, the DESTROY method will check the process id of the handle and, if
 different from the current process id, it will set the I<InactiveDestroy> attribute.
+It is strongly recommended that C<AutoInactiveDestroy> is enabled on all new code
+(it's only not enabled by default to avoid backwards compatibility problems).
 
 This is the example it's designed to deal with:
 
@@ -4936,7 +4947,7 @@ unknown or unimplemented information types. For example:
 See L</"Standards Reference Information"> for more detailed information
 about the information types and their meanings and possible return values.
 
-The DBI::Const::GetInfoType module exports a %GetInfoType hash that
+The L<DBI::Const::GetInfoType> module exports a %GetInfoType hash that
 can be used to map info type names to numbers. For example:
 
   $database_version = $dbh->get_info( $GetInfoType{SQL_DBMS_VER} );
@@ -7071,7 +7082,7 @@ For example:
   my $sth2 = $dbh->prepare( $sth1->{Statement} );
   my $ParamValues = $sth1->{ParamValues} || {};
   my $ParamTypes  = $sth1->{ParamTypes}  || {};
-  $sth2->bind_param($_, $ParamValues->{$_} $ParamTypes->{$_})
+  $sth2->bind_param($_, $ParamValues->{$_}, $ParamTypes->{$_})
     for keys %{ {%$ParamValues, %$ParamTypes} };
   $sth2->execute();
 
@@ -1856,7 +1856,7 @@ dbih_sth_bind_col(SV *sth, SV *col, SV *ref, SV *attribs)
         PERL_UNUSED_VAR(attribs);
         croak("Statement has no result columns to bind%s",
             DBIc_ACTIVE(imp_sth)
-                ? "" : " (perhaps you need to call execute first)");
+                ? "" : " (perhaps you need to successfully call execute first, or again)");
     }
 
     if ( (av = DBIc_FIELDS_AV(imp_sth)) == Nullav)
@@ -3147,6 +3147,7 @@ XS(XS_DBI_dispatch);            /* prototype to pass -Wmissing-prototypes */
 XS(XS_DBI_dispatch)
 {
     dXSARGS;
+    dORIGMARK;
     dMY_CXT;
 
     SV *h   = ST(0);            /* the DBI handle we are working with   */
@@ -3447,6 +3448,7 @@ XS(XS_DBI_dispatch)
                     XPUSHs(*hp);
                     PUTBACK;
                     call_method("DESTROY", G_DISCARD|G_EVAL|G_KEEPERR);
+                    MSPAGAIN;
                 }
                 else {
                     imp_xxh_t *imp_xxh = dbih_getcom2(aTHX_ *hp, 0);
@@ -3539,8 +3541,8 @@ XS(XS_DBI_dispatch)
         SV *code = SvRV(*hook_svp);
         I32 skip_dispatch = 0;
         if (trace_level)
-            PerlIO_printf(DBILOGFP, "%c   {{ %s callback %s being invoked\n",
-                (PL_dirty?'!':' '), meth_name, neatsvpv(*hook_svp,0));
+            PerlIO_printf(DBILOGFP, "%c   {{ %s callback %s being invoked with %ld args\n",
+                (PL_dirty?'!':' '), meth_name, neatsvpv(*hook_svp,0), (long)items);
 
         /* we don't use ENTER,SAVETMPS & FREETMPS,LEAVE because we may need mortal
          * results to live long enough to be returned to our caller
@@ -3562,7 +3564,7 @@ XS(XS_DBI_dispatch)
         }
         PUTBACK;
         outitems = call_sv(code, G_ARRAY); /* call the callback code */
-        SPAGAIN;
+        MSPAGAIN;
 
         /* The callback code can undef $_ to indicate to skip dispatch */
         skip_dispatch = !SvOK(DEFSV);
@@ -3890,7 +3892,7 @@ XS(XS_DBI_dispatch)
                 XPUSHs(&PL_sv_yes);
                 PUTBACK;
                 call_method("STORE", G_DISCARD);
-                SPAGAIN;
+                MSPAGAIN;
             }
         }
     }
@@ -4047,7 +4049,7 @@ XS(XS_DBI_dispatch)
             XPUSHs( result );
             PUTBACK;
             items = call_sv(*hook_svp, G_SCALAR);
-            SPAGAIN;
+            MSPAGAIN;
             status = (items) ? POPs : &PL_sv_undef;
             PUTBACK;
             if (trace_level)
@@ -4155,7 +4157,7 @@ preparse(SV *dbh, const char *statement, IV ps_return, IV ps_accept, void *foo)
     char rt_comment = '\0';
     char *dest, *start;
     const char *src;
-    const char *style = "", *laststyle = '\0';
+    const char *style = "", *laststyle = NULL;
     SV *new_stmt_sv;
 
     (void)foo;
@@ -5445,6 +5447,19 @@ FETCH(h, keysv)
     ST(0) = dbih_get_attr_k(h, keysv, 0);
     (void)cv;
 
+void
+DELETE(h, keysv)
+    SV *        h
+    SV *        keysv
+    CODE:
+    /* only private_* keys can be deleted, for others DELETE acts like FETCH */
+    /* because the DBI internals rely on certain handle attributes existing  */
+    if (strnEQ(SvPV_nolen(keysv),"private_",8))
+        ST(0) = hv_delete_ent((HV*)SvRV(h), keysv, 0, 0);
+    else
+        ST(0) = dbih_get_attr_k(h, keysv, 0);
+    (void)cv;
+
 
 void
 private_data(h)
@@ -4,7 +4,7 @@
       "Tim Bunce (dbi-users@perl.org)"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "ExtUtils::MakeMaker version 6.76, CPAN::Meta::Converter version 2.132510",
+   "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.142690",
    "license" : [
       "perl_5"
    ],
@@ -55,9 +55,10 @@
       "repository" : {
          "url" : "https://github.com/perl5-dbi/dbi"
       },
+      "x_IRC" : "irc://irc.perl.org/#dbi",
       "x_MailingList" : "mailto:dbi-dev@perl.org"
    },
-   "version" : "1.631",
+   "version" : "1.632",
    "x_suggests" : {
       "Clone" : 0.34,
       "DB_File" : 0,
@@ -3,37 +3,38 @@ abstract: 'Database independent interface for Perl'
 author:
   - 'Tim Bunce (dbi-users@perl.org)'
 build_requires:
-  ExtUtils::MakeMaker: 6.48
-  Test::Simple: 0.90
+  ExtUtils::MakeMaker: '6.48'
+  Test::Simple: '0.90'
 configure_requires:
-  ExtUtils::MakeMaker: 0
+  ExtUtils::MakeMaker: '0'
 conflicts:
-  DBD::Amazon: 0.10
-  DBD::AnyData: 0.110
-  DBD::CSV: 0.36
-  DBD::Google: 0.51
-  DBD::PO: 2.10
-  DBD::RAM: 0.072
-  SQL::Statement: 1.33
+  DBD::Amazon: '0.10'
+  DBD::AnyData: '0.110'
+  DBD::CSV: '0.36'
+  DBD::Google: '0.51'
+  DBD::PO: '2.10'
+  DBD::RAM: '0.072'
+  SQL::Statement: '1.33'
 dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.76, CPAN::Meta::Converter version 2.132510'
+generated_by: 'ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.142690'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: DBI
 no_index:
   directory:
     - t
     - inc
 requires:
-  perl: 5.008
+  perl: '5.008'
 resources:
+  IRC: irc://irc.perl.org/#dbi
   MailingList: mailto:dbi-dev@perl.org
   homepage: http://dbi.perl.org/
   license: http://dev.perl.org/licenses/
   repository: https://github.com/perl5-dbi/dbi
-version: 1.631
+version: '1.632'
 x_suggests:
   Clone: 0.34
   DB_File: 0
@@ -64,6 +64,7 @@ my %opts = (
 	    MailingList => 'mailto:dbi-dev@perl.org',
 	    license     => 'http://dev.perl.org/licenses/',
 	    homepage    => 'http://dbi.perl.org/',
+	    IRC		=> 'irc://irc.perl.org/#dbi',
 	},
 	suggests => {
 	    'RPC::PlServer'  => 0.2001,
@@ -35,7 +35,7 @@ use base qw( DBI::DBD::SqlEngine );
 use Carp;
 use vars qw( @ISA $VERSION $drh );
 
-$VERSION = "0.42";
+$VERSION = "0.43";
 
 $drh = undef;		# holds driver handle(s) once initialized
 
@@ -85,6 +85,8 @@ use warnings;
 
 use vars qw( @ISA $imp_data_size );
 
+use Carp;
+
 @DBD::File::dr::ISA           = qw( DBI::DBD::SqlEngine::dr );
 $DBD::File::dr::imp_data_size = 0;
 
@@ -100,6 +102,31 @@ sub dsn_quote
 # XXX rewrite using TableConfig ...
 sub default_table_source { "DBD::File::TableSource::FileSystem" }
 
+sub connect
+{
+    my ($drh, $dbname, $user, $auth, $attr) = @_;
+
+    # We do not (yet) care about conflicting attributes here
+    # my $dbh = DBI->connect ("dbi:CSV:f_dir=test", undef, undef, { f_dir => "text" });
+    # will test here that both test and text should exist
+    if (my $attr_hash = (DBI->parse_dsn ($dbname))[3]) {
+	if (defined $attr_hash->{f_dir} && ! -d $attr_hash->{f_dir}) {
+	    my $msg = "No such directory '$attr_hash->{f_dir}";
+	    $drh->set_err (2, $msg);
+	    $attr_hash->{RaiseError} and croak $msg;
+	    return;
+	    }
+	}
+    if ($attr and defined $attr->{f_dir} && ! -d $attr->{f_dir}) {
+	my $msg = "No such directory '$attr->{f_dir}";
+	$drh->set_err (2, $msg);
+	$attr->{RaiseError} and croak $msg;
+	return;
+	}
+
+    return $drh->SUPER::connect ($dbname, $user, $auth, $attr);
+    } # connect
+
 sub disconnect_all
 {
     } # disconnect_all
@@ -130,7 +157,7 @@ sub data_sources
 {
     my ($dbh, $attr, @other) = @_;
     ref ($attr) eq "HASH" or $attr = {};
-    exists $attr->{f_dir}        or $attr->{f_dir}     = $dbh->{f_dir};
+    exists $attr->{f_dir}        or $attr->{f_dir}        = $dbh->{f_dir};
     exists $attr->{f_dir_search} or $attr->{f_dir_search} = $dbh->{f_dir_search};
     return $dbh->SUPER::data_sources ($attr, @other);
     } # data_source
@@ -343,6 +370,10 @@ sub data_sources
 	? $attr->{f_dir}
 	: File::Spec->curdir ();
     defined $dir or return; # Stream-based databases do not have f_dir
+    unless (-d $dir && -r $dir && -x $dir) {
+	$drh->set_err ($DBI::stderr, "Cannot use directory $dir from f_dir");
+	return;
+	}
     my %attrs;
     $attr and %attrs = %$attr;
     delete $attrs{f_dir};
@@ -551,7 +551,7 @@
             go_last_insert_id_args => $lii_args,
             go_cache => $go_cache,
         });
-        $sth->STORE(Active => 0);
+        $sth->STORE(Active => 0); # XXX needed? It should be the default
 
         my $skip_prepare_check = $policy->skip_prepare_check($attr, $dbh, $statement, $attr, $sth);
         if (not $skip_prepare_check) {
@@ -759,7 +759,6 @@ proxying the connect_cached method. The proxy server will hold the
 database connections open in a cache. The CGI script then trades the
 database connect/disconnect overhead for the DBD::Proxy
 connect/disconnect overhead which is typically much less.
-I<Note that the connect_cached method is new and still experimental.>
 
 
 =head1 CONNECTING TO THE DATABASE
@@ -846,7 +845,7 @@ less secure than the usercipher/userkey secret and readable by anyone.
 The usercipher/userkey secret is B<your> private secret.
 
 Of course encryption requires an appropriately configured server. See
-<DBD::ProxyServer/CONFIGURATION FILE>.
+L<DBD::ProxyServer/CONFIGURATION FILE>.
 
 =item debug
 
@@ -974,6 +973,13 @@ The workaround is storing the modified local copy back to the server:
   $dbh->{"csv_tables"} = $tables;
 
 
+=head1 SECURITY WARNING
+
+L<RPC::PlClient> used underneath is not secure due to serializing and
+deserializing data with L<Storable> module. Use the proxy driver only in
+trusted environment.
+
+
 =head1 AUTHOR AND COPYRIGHT
 
 This module is Copyright (c) 1997, 1998
@@ -30,8 +30,15 @@ L<DBI::DBD/CREATING A NEW DRIVER>.
 
 =head1 CREATING DRIVER CLASSES
 
-Do you have an entry in DBI's DBD registry? For this guide, a prefix of
-C<foo_> is assumed.
+Do you have an entry in DBI's DBD registry? DBI::DBD::SqlEngine expect
+having a unique prefix for every driver class in inheritance chain.
+
+It's easy to get a prefix - just drop the DBI team a note
+(L<DBI/GETTING_HELP>). If you want for some reason hide your work, take
+a look at L<Class::Method::Modifiers> how to wrap a private prefix method
+around existing C<driver_prefix>.
+
+For this guide, a prefix of C<foo_> is assumed.
 
 =head2 Sample Skeleton
 
@@ -95,6 +95,12 @@ EOI
             $dbclass->install_method($method);
         }
     }
+    else
+    {
+        warn "Using DBI::DBD::SqlEngine with unregistered driver $class.\n"
+          . "Reading documentation how to prevent is strongly recommended.\n";
+
+    }
 
     # XXX inject DBD::XXX::Statement unless exists
 
@@ -1693,6 +1699,9 @@ Currently the API of DBI::DBD::SqlEngine is experimental and will
 likely change in the near future to provide the table meta data basics
 like DBD::File.
 
+DBI::DBD::SqlEngine expects that any driver in inheritance chain has
+a L<DBI prefix|DBI::DBD/The_database_handle_constructor>.
+
 =head2 Metadata
 
 The following attributes are handled by DBI itself and not by
@@ -831,7 +831,12 @@ sub as_text {
         for (@path) {
             s/[\r\n]+/ /g;
             s/$separator_re/ /g;
-            $_ = sprintf $format_path_element, $_, ++$idx;
+            ++$idx;
+            if ($format_path_element eq "%s") {
+              $_ = sprintf $format_path_element, $_;
+            } else {
+              $_ = sprintf $format_path_element, $_, $idx;
+            }
         }
         push @text, sprintf $format,
             join($separator, @path),                  # 1=path
@@ -867,6 +867,13 @@ Don't try to put parameters into the sql-query like this:
 =back
 
 
+=head1 SECURITY WARNING
+
+L<RPC::PlServer> used underneath is not secure due to serializing and
+deserializing data with L<Storable> module. Use the proxy driver only in
+trusted environment.
+
+
 =head1 AUTHOR
 
     Copyright (c) 1997    Jochen Wiedmann
@@ -504,14 +504,19 @@ sub _setup_handle {
 	    $h_inner->{$_} = $parent->{$_}
 		if exists $parent->{$_} && !exists $h_inner->{$_};
 	}
-	if (ref($parent) =~ /::db$/) {
+	if (ref($parent) =~ /::db$/) { # is sth
 	    $h_inner->{Database} = $parent;
 	    $parent->{Statement} = $h_inner->{Statement};
 	    $h_inner->{NUM_OF_PARAMS} = 0;
+            $h_inner->{Active} = 0; # driver sets true when there's data to fetch
 	}
-	elsif (ref($parent) =~ /::dr$/){
+	elsif (ref($parent) =~ /::dr$/){ # is dbh
 	    $h_inner->{Driver} = $parent;
+            $h_inner->{Active} = 0;
 	}
+        else {
+            warn "panic: ".ref($parent); # should never happen
+        }
 	$h_inner->{dbi_pp_parent} = $parent;
 
 	# add to the parent's ChildHandles
@@ -536,11 +541,11 @@ sub _setup_handle {
 	$h_inner->{LongReadLen}		||= 80;
 	$h_inner->{ChildHandles}        ||= [] if $HAS_WEAKEN;
 	$h_inner->{Type}                ||= 'dr';
+        $h_inner->{Active}              = 1;
     }
     $h_inner->{"dbi_pp_call_depth"} = 0;
     $h_inner->{"dbi_pp_pid"} = $$;
     $h_inner->{ErrCount} = 0;
-    $h_inner->{Active} = 1;
 }
 
 sub constant {
@@ -888,6 +893,11 @@ sub STORE {
     $h->{$key} = $is_flag_attribute{$key} ? !!$value : $value;
     return 1;
 }
+sub DELETE {
+    my ($h, $key) = @_;
+    return $h->FETCH($key) unless $key =~ /^private_/;
+    return delete $h->{$key};
+}
 sub err    { return shift->{err}    }
 sub errstr { return shift->{errstr} }
 sub state  { return shift->{state}  }
@@ -79,6 +79,13 @@ is_deeply [ $dbh->FETCH_many(qw(HandleError FetchHashKeyName LongReadLen ErrCoun
           [ undef, qw(NAME 80 0) ], 'should be able to FETCH_many';
 
 is $dbh->{examplep_private_dbh_attrib}, 42, 'should see driver-private dbh attribute value';
+is delete $dbh->{examplep_private_dbh_attrib}, 42, 'delete on non-private attribute acts like fetch';
+is $dbh->{examplep_private_dbh_attrib}, 42, 'value unchanged after delete';
+
+$dbh->{private_foo} = 42;
+is $dbh->{private_foo}, 42, 'should see private_foo dbh attribute value';
+is delete $dbh->{private_foo}, 42, 'delete should return private_foo dbh attribute value';
+is $dbh->{private_foo}, undef, 'value of private_foo after delete should be undef';
 
 # Raise an error.
 eval { 
@@ -207,6 +207,31 @@ ok ($dbh = DBI->connect ("dbi:File:", undef, undef, {
 ok ($dbh->do ("drop table $tbl"), "table drop");
 is (-s $tbl_file, undef, "Test table removed"); # -s => size test
 
+# ==================== Nonexisting top-dir ========================
+my %drh = DBI->installed_drivers;
+my $qer = qr{\bNo such directory};
+foreach my $tld ("./non-existing", "nonexisting_folder", "/Fr-dle/hurd0k/ok$$") {
+    is (DBI->connect ("dbi:File:", undef, undef, {
+	f_dir      => $tld,
+
+	RaiseError => 0,
+	PrintError => 0,
+	}), undef, "Should not be able to open a DB to $tld");
+    like ($DBI::errstr, $qer, "Error message");
+    $drh{File}->set_err (undef, "");
+    is ($DBI::errstr, undef, "Cleared error");
+    my $dbh;
+    eval { $dbh = DBI->connect ("dbi:File:", undef, undef, {
+	f_dir      => $tld,
+
+	RaiseError => 1,
+	PrintError => 0,
+	})};
+    is ($dbh, undef, "connect () should die on $tld with RaiseError");
+    like ($@,           $qer, "croak message");
+    like ($DBI::errstr, $qer, "Error message");
+    }
+
 done_testing ();
 
 sub DBD::File::Table::fetch_row ($$)
@@ -221,6 +221,16 @@ is $called{execute}, 1, 'Execute callback should have been called';
 ok $sth->fetch, 'Fetch';
 is $called{fetch}, 1, 'Fetch callback should have been called';
 
+# stress test for stack reallocation and mark handling -- RT#86744
+my $stress_count = 3000;
+my $place_holders = join(',', ('?') x $stress_count);
+my @params = ('t') x $stress_count;
+my $stress_dbh = DBI->connect( 'DBI:NullP:test');
+my $stress_sth = $stress_dbh->prepare("select 1");
+$stress_sth->{Callbacks}{execute} = sub { return; };
+$stress_sth->execute(@params);
+
+
 done_testing();
 
 __END__