From: Paul Mooney Date: Thu, 10 Mar 2016 10:50:57 +0000 (+0000) Subject: Avoid infinite loop if save point does not exist X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f5f0cb1dd;p=dbsrgits%2FDBIx-Class.git Avoid infinite loop if save point does not exist --- diff --git a/AUTHORS b/AUTHORS index 264ee55..5193ba8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -162,6 +162,7 @@ Peter Valdemar Mørch peter: Peter Collingbourne phaylon: Robert Sedlacek plu: Johannes Plunien +pmooney: Paul Mooney Possum: Daniel LeWarne pplu: Jose Luis Martinez quicksilver: Jules Bean diff --git a/Changes b/Changes index accc48c..7b2a01d 100644 --- a/Changes +++ b/Changes @@ -45,6 +45,7 @@ Revision history for DBIx::Class create()/populate() - Remove spurious exception warping in ::Replicated::execute_reliably (RT#113339) + - Fix infinite loop on ->svp_release("nonexistent_savepoint") (GH#97) - Fix spurious ROLLBACK statements when a TxnScopeGuard fails a commit of a transaction with deferred FK checks: a guard is now inactivated immediately before the commit is attempted (RT#107159) diff --git a/lib/DBIx/Class/Storage.pm b/lib/DBIx/Class/Storage.pm index 45839e1..f512843 100644 --- a/lib/DBIx/Class/Storage.pm +++ b/lib/DBIx/Class/Storage.pm @@ -431,12 +431,15 @@ sub svp_release { if (defined $name) { my @stack = @{ $self->savepoints }; - my $svp; + my $svp = ''; - do { $svp = pop @stack } until $svp eq $name; + while( $svp ne $name ) { - $self->throw_exception ("Savepoint '$name' does not exist") - unless $svp; + $self->throw_exception ("Savepoint '$name' does not exist") + unless @stack; + + $svp = pop @stack; + } $self->savepoints(\@stack); # put back what's left } diff --git a/t/storage/savepoints.t b/t/storage/savepoints.t index b125d6e..8960a5e 100644 --- a/t/storage/savepoints.t +++ b/t/storage/savepoints.t @@ -7,6 +7,7 @@ use Test::More; use Test::Exception; use DBIx::Class::Optional::Dependencies; use DBIx::Class::_Util qw(sigwarn_silencer scope_guard); +use Scalar::Util 'weaken'; use DBICTest; @@ -240,6 +241,17 @@ for ('', keys %$env2optdep) { SKIP: { # make sure a fresh txn will work after above $schema->storage->txn_do(sub { ok "noop" } ); +### Make sure non-existend savepoint release doesn't infloop itself + { + weaken( my $s = $schema ); + + throws_ok { + $s->storage->txn_do(sub { $s->svp_release('wibble') }) + } qr/Savepoint 'wibble' does not exist/, + "Calling svp_release on a non-existant savepoint throws expected error" + ; + } + ### cleanupz $schema->storage->dbh_do(sub { $_[1]->do("DROP TABLE artist") }); }}