From 15146353f9e16f68a69f7fdb25dd1e9059cad5c4 Mon Sep 17 00:00:00 2001 From: Daniel Nichter Date: Thu, 24 May 2012 10:32:39 -0600 Subject: [PATCH] Use regex to split DSN parts to allow commas in values. --- lib/DSNParser.pm | 13 ++++++++++- t/lib/DSNParser.t | 55 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/DSNParser.pm b/lib/DSNParser.pm index c59a6c60..efa79819 100644 --- a/lib/DSNParser.pm +++ b/lib/DSNParser.pm @@ -32,6 +32,17 @@ use Data::Dumper; $Data::Dumper::Indent = 0; $Data::Dumper::Quotekeys = 0; +# Passwords may contain commas. +# https://bugs.launchpad.net/percona-toolkit/+bug/886077 +my $dsn_sep = qr/ # Separate DSN parts by + , # comma + (?= # followed by either + (?:\Z # the end of the string, or + |[a-zA-Z]= # start of another DSN part + ) + ) +/x; + eval { require DBI; }; @@ -126,7 +137,7 @@ sub parse { my $opts = $self->{opts}; # Parse given props - foreach my $dsn_part ( split(/,/, $dsn) ) { + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { # Handle the typical DSN parts like h=host, P=3306, etc. $given_props{$prop_key} = $prop_val; diff --git a/t/lib/DSNParser.t b/t/lib/DSNParser.t index 650ccbf6..3b81ff25 100644 --- a/t/lib/DSNParser.t +++ b/t/lib/DSNParser.t @@ -9,12 +9,14 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 27; +use Test::More tests => 33; use DSNParser; use OptionParser; use PerconaTest; +use Data::Dumper; + my $opts = [ { key => 'A', @@ -82,6 +84,20 @@ is_deeply( 'Basic DSN' ); +is_deeply( + $dp->parse('S=/tmp/sock'), + { u => undef, + p => undef, + S => '/tmp/sock', + h => undef, + P => undef, + F => undef, + D => undef, + A => undef, + }, + 'Basic DSN with one part' +); + is_deeply( $dp->parse('u=a,p=b,A=utf8'), { u => 'a', @@ -392,6 +408,8 @@ is_deeply( 'Copy DSN and overwrite destination' ); +pop @$opts; # Remove t part. + # ############################################################################# # Issue 93: DBI error messages can include full SQL # ############################################################################# @@ -461,6 +479,41 @@ SKIP: { diag(`$trunk/sandbox/stop-sandbox 12348 >/dev/null`); }; +# ############################################################################# +# Passwords with commas don't work, expose part of password +# https://bugs.launchpad.net/percona-toolkit/+bug/886077 +# ############################################################################# +$dp = new DSNParser(opts => $opts); + +sub test_password_comma { + my ($dsn_string, $pass, $port, $name) = @_; + my $dsn = $dp->parse($dsn_string); + is_deeply( + $dsn, + { u => 'a', + p => $pass, + S => undef, + h => undef, + P => $port, + F => undef, + D => undef, + A => undef, + }, + "$name (bug 886077)" + ) or diag(Dumper($dsn)); +} + +my @password_commas = ( + ['u=a,p=foo,xxx,P=12345', 'foo,xxx', 12345, 'Pass with comma'], + ['u=a,p=foo,xxx', 'foo,xxx', undef, 'Pass with comma, last part'], + ['u=a,p=foo,,P=12345', 'foo,', 12345, 'Pass ends with comma'], + ['u=a,p=foo,,', 'foo,', undef, 'Pass ends with comma, last part'], + ['u=a,p=,,P=12345', ',', 12345, 'Pass is a comma'], +); +foreach my $password_comma ( @password_commas ) { + test_password_comma(@$password_comma); +} + # ############################################################################# # Done. # #############################################################################