From d673a0b5320faa9f97a91422e32dbb179b20fea1 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Sun, 25 Dec 2016 05:53:12 -0800 Subject: [PATCH] Properly escape DSN parameters. --- builtin/providers/postgresql/config.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/builtin/providers/postgresql/config.go b/builtin/providers/postgresql/config.go index 005cd6511..125c2d79c 100644 --- a/builtin/providers/postgresql/config.go +++ b/builtin/providers/postgresql/config.go @@ -1,6 +1,7 @@ package postgresql import ( + "bytes" "database/sql" "fmt" "log" @@ -31,12 +32,31 @@ type Client struct { func (c *Config) NewClient() (*Client, error) { // NOTE: dbname must come before user otherwise dbname will be set to // user. - const dsnFmt = "host='%s' port='%d' dbname='%s' user='%s' password='%s' sslmode='%s' fallback_application_name='%s' connect_timeout='%d'" + const dsnFmt = "host=%s port=%d dbname=%s user=%s password=%s sslmode=%s fallback_application_name=%s connect_timeout=%d" - logDSN := fmt.Sprintf(dsnFmt, c.Host, c.Port, c.Database, c.Username, "", c.SSLMode, c.ApplicationName, c.ConnectTimeoutSec) + // Quote empty strings or strings that contain whitespace + q := func(s string) string { + b := bytes.NewBufferString(`'`) + b.Grow(len(s) + 2) + for _, r := range s { + switch r { + case '\'': + b.WriteString(`\'`) + case '\\': + b.WriteString(`\\`) + default: + b.WriteRune(r) + } + } + + b.WriteString(`'`) + return b.String() + } + + logDSN := fmt.Sprintf(dsnFmt, q(c.Host), c.Port, q(c.Database), q(c.Username), q(""), q(c.SSLMode), q(c.ApplicationName), c.ConnectTimeoutSec) log.Printf("[INFO] PostgreSQL DSN: `%s`", logDSN) - connStr := fmt.Sprintf(dsnFmt, c.Host, c.Port, c.Database, c.Username, c.Password, c.SSLMode, c.ApplicationName, c.ConnectTimeoutSec) + connStr := fmt.Sprintf(dsnFmt, q(c.Host), c.Port, q(c.Database), q(c.Username), q(c.Password), q(c.SSLMode), q(c.ApplicationName), c.ConnectTimeoutSec) client := Client{ connStr: connStr, username: c.Username,