Skip to content

Commit a8b98e9

Browse files
committed
Fixed risk of memory corruption with many arguments to methods RT#86744
1 parent cd6755f commit a8b98e9

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Changes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ DBI::Changes - List of significant changes to the DBI
88

99
=head2 Changes in DBI 1.632
1010

11+
Fixed risk of memory corruption with many arguments to methods
12+
originally reported by OSCHWALD for Callbacks but may apply
13+
to other functionality in DBI method dispatch RT#86744.
1114
Fixed DBD::PurePerl to not set $sth->{Active} true by default
1215
drivers are expected to set it true as needed.
1316
Fixed DBI::DBD::SqlEngine to complain loudly when prerequite

DBI.xs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,6 +3147,7 @@ XS(XS_DBI_dispatch); /* prototype to pass -Wmissing-prototypes */
31473147
XS(XS_DBI_dispatch)
31483148
{
31493149
dXSARGS;
3150+
dORIGMARK;
31503151
dMY_CXT;
31513152

31523153
SV *h = ST(0); /* the DBI handle we are working with */
@@ -3447,6 +3448,7 @@ XS(XS_DBI_dispatch)
34473448
XPUSHs(*hp);
34483449
PUTBACK;
34493450
call_method("DESTROY", G_DISCARD|G_EVAL|G_KEEPERR);
3451+
MSPAGAIN;
34503452
}
34513453
else {
34523454
imp_xxh_t *imp_xxh = dbih_getcom2(aTHX_ *hp, 0);
@@ -3539,8 +3541,8 @@ XS(XS_DBI_dispatch)
35393541
SV *code = SvRV(*hook_svp);
35403542
I32 skip_dispatch = 0;
35413543
if (trace_level)
3542-
PerlIO_printf(DBILOGFP, "%c {{ %s callback %s being invoked\n",
3543-
(PL_dirty?'!':' '), meth_name, neatsvpv(*hook_svp,0));
3544+
PerlIO_printf(DBILOGFP, "%c {{ %s callback %s being invoked with %ld args\n",
3545+
(PL_dirty?'!':' '), meth_name, neatsvpv(*hook_svp,0), (long)items);
35443546

35453547
/* we don't use ENTER,SAVETMPS & FREETMPS,LEAVE because we may need mortal
35463548
* results to live long enough to be returned to our caller
@@ -3562,7 +3564,7 @@ XS(XS_DBI_dispatch)
35623564
}
35633565
PUTBACK;
35643566
outitems = call_sv(code, G_ARRAY); /* call the callback code */
3565-
SPAGAIN;
3567+
MSPAGAIN;
35663568

35673569
/* The callback code can undef $_ to indicate to skip dispatch */
35683570
skip_dispatch = !SvOK(DEFSV);
@@ -3890,7 +3892,7 @@ XS(XS_DBI_dispatch)
38903892
XPUSHs(&PL_sv_yes);
38913893
PUTBACK;
38923894
call_method("STORE", G_DISCARD);
3893-
SPAGAIN;
3895+
MSPAGAIN;
38943896
}
38953897
}
38963898
}
@@ -4047,7 +4049,7 @@ XS(XS_DBI_dispatch)
40474049
XPUSHs( result );
40484050
PUTBACK;
40494051
items = call_sv(*hook_svp, G_SCALAR);
4050-
SPAGAIN;
4052+
MSPAGAIN;
40514053
status = (items) ? POPs : &PL_sv_undef;
40524054
PUTBACK;
40534055
if (trace_level)

t/70callbacks.t

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ is $called{execute}, 1, 'Execute callback should have been called';
221221
ok $sth->fetch, 'Fetch';
222222
is $called{fetch}, 1, 'Fetch callback should have been called';
223223

224+
# stress test for stack reallocation and mark handling -- RT#86744
225+
my $stress_count = 3000;
226+
my $place_holders = join(',', ('?') x $stress_count);
227+
my @params = ('t') x $stress_count;
228+
my $stress_dbh = DBI->connect( 'DBI:NullP:test');
229+
my $stress_sth = $stress_dbh->prepare("select 1");
230+
$stress_sth->{Callbacks}{execute} = sub { return; };
231+
$stress_sth->execute(@params);
232+
233+
224234
done_testing();
225235

226236
__END__

0 commit comments

Comments
 (0)