Skip to content

Commit 6d1a06d

Browse files
committed
Fix protocol parsing
1 parent 3f855aa commit 6d1a06d

File tree

3 files changed

+24
-27
lines changed

3 files changed

+24
-27
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ A DSN in its fullest form:
7878
username:password@protocol(address)/dbname?param=value
7979
```
8080

81-
Except of the databasename, all values are optional. So the minimal DSN is:
81+
Except for the databasename, all values are optional. So the minimal DSN is:
8282
```
8383
/dbname
8484
```

utils.go

+17-23
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ func parseDSN(dsn string) (cfg *config, err error) {
8080
// TODO: use strings.IndexByte when we can depend on Go 1.2
8181

8282
// [user[:password]@][net[(addr)]]/dbname[?param1=value1&paramN=valueN]
83-
// Find the last '/' (since the password might contain a '/')
83+
// Find the last '/' (since the password or the net addr might contain a '/')
8484
for i := len(dsn) - 1; i >= 0; i-- {
8585
if dsn[i] == '/' {
86-
var j int
86+
var j, k int
8787

8888
// left part is empty if i <= 0
8989
if i > 0 {
@@ -93,7 +93,6 @@ func parseDSN(dsn string) (cfg *config, err error) {
9393
if dsn[j] == '@' {
9494
// username[:password]
9595
// Find the first ':' in dsn[:j]
96-
var k int
9796
for k = 0; k < j; k++ {
9897
if dsn[k] == ':' {
9998
cfg.passwd = dsn[k+1 : j]
@@ -102,31 +101,26 @@ func parseDSN(dsn string) (cfg *config, err error) {
102101
}
103102
cfg.user = dsn[:k]
104103

105-
// [protocol[(address)]]
106-
// Find the first '(' in dsn[j+1:i]
107-
for k = j + 1; k < i; k++ {
108-
if dsn[k] == '(' {
109-
// dsn[i-1] must be == ')' if an adress is specified
110-
if dsn[i-1] != ')' {
111-
if strings.ContainsRune(dsn[k+1:i], ')') {
112-
return nil, errInvalidDSNUnescaped
113-
}
114-
return nil, errInvalidDSNAddr
115-
}
116-
cfg.addr = dsn[k+1 : i-1]
117-
break
118-
}
119-
}
120-
cfg.net = dsn[j+1 : k]
121-
122104
break
123105
}
124106
}
125107

126-
// non-empty left part must contain an '@'
127-
if j < 0 {
128-
return nil, errInvalidDSNUnescaped
108+
// [protocol[(address)]]
109+
// Find the first '(' in dsn[j+1:i]
110+
for k = j + 1; k < i; k++ {
111+
if dsn[k] == '(' {
112+
// dsn[i-1] must be == ')' if an adress is specified
113+
if dsn[i-1] != ')' {
114+
if strings.ContainsRune(dsn[k+1:i], ')') {
115+
return nil, errInvalidDSNUnescaped
116+
}
117+
return nil, errInvalidDSNAddr
118+
}
119+
cfg.addr = dsn[k+1 : i-1]
120+
break
121+
}
129122
}
123+
cfg.net = dsn[j+1 : k]
130124
}
131125

132126
// dbname[?param1=value1&...&paramN=valueN]

utils_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var testDSNs = []struct {
3030
{"/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p timeout:0 tls:<nil> allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
3131
{"", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p timeout:0 tls:<nil> allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
3232
{"user:p@/ssword@/", "&{user:user passwd:p@/ssword net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p timeout:0 tls:<nil> allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
33-
{"@unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p timeout:0 tls:<nil> allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
33+
{"unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p timeout:0 tls:<nil> allowAllFiles:false allowOldPasswords:false clientFoundRows:false}", time.UTC},
3434
}
3535

3636
func TestDSNParser(t *testing.T) {
@@ -56,8 +56,11 @@ func TestDSNParser(t *testing.T) {
5656

5757
func TestDSNParserInvalid(t *testing.T) {
5858
var invalidDSNs = []string{
59-
"asdf/dbname",
60-
"@net(addr/",
59+
"@net(addr/", // no closing brace
60+
"@tcp(/", // no closing brace
61+
"tcp(/", // no closing brace
62+
"(/", // no closing brace
63+
"net(addr)//", // unescaped
6164
//"/dbname?arg=/some/unescaped/path",
6265
}
6366

0 commit comments

Comments
 (0)