From 4a7d9870ef6a5a247ef532192988b01bf13cc110 Mon Sep 17 00:00:00 2001 From: Andrew Bosonchenko Date: Sat, 13 Jun 2020 19:05:47 +0300 Subject: [PATCH 1/4] removed minor from version fixed server version detection for builds like "11.2 (Debian 11.2-1.pgdg90+1)" --- conn.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/conn.go b/conn.go index b3ab14d3c..cfd142d45 100644 --- a/conn.go +++ b/conn.go @@ -1689,10 +1689,9 @@ func (cn *conn) processParameterStatus(r *readBuf) { case "server_version": var major1 int var major2 int - var minor int - _, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor) + _, err = fmt.Sscanf(r.string(), "%d.%d", &major1, &major2) if err == nil { - cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor + cn.parameterStatus.serverVersion = major1*10000 + major2*100 } case "TimeZone": From 2a9e9edbc676b5886cd446089ca450693e327f73 Mon Sep 17 00:00:00 2001 From: Vegard Stikbakke Date: Wed, 14 Apr 2021 12:58:37 +0200 Subject: [PATCH 2/4] Fix string quoting in an example in Array --- array.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.go b/array.go index 405da2368..7806a31f3 100644 --- a/array.go +++ b/array.go @@ -22,7 +22,7 @@ var typeSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem() // db.Query(`SELECT * FROM t WHERE id = ANY($1)`, pq.Array([]int{235, 401})) // // var x []sql.NullInt64 -// db.QueryRow('SELECT ARRAY[235, 401]').Scan(pq.Array(&x)) +// db.QueryRow(`SELECT ARRAY[235, 401]`).Scan(pq.Array(&x)) // // Scanning multi-dimensional arrays is not supported. Arrays where the lower // bound is not one (such as `[0:0]={1}') are not supported. From d07609080cd0b3a1552f718796a7b095c057689c Mon Sep 17 00:00:00 2001 From: Bjorn <47388782+bjornouderoelink@users.noreply.github.com> Date: Sun, 18 Apr 2021 14:54:43 +0200 Subject: [PATCH 3/4] Fix concurrent map writes. This commit should fix an issue with concurrent map writes by making the opts values map in separate connections not reference the same underlying data. --- conn.go | 8 +++++++- conn_go18.go | 13 +++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/conn.go b/conn.go index 368013856..4f35614f3 100644 --- a/conn.go +++ b/conn.go @@ -298,7 +298,13 @@ func (c *Connector) open(ctx context.Context) (cn *conn, err error) { // the user. defer errRecoverNoErrBadConn(&err) - o := c.opts + // Create a new values map (copy). This makes it so maps in different + // connections do not reference the same underlying data structure, so it + // is safe for multiple connections to concurrently write to their opts. + o := make(values) + for k, v := range c.opts { + o[k] = v + } bad := &atomic.Value{} bad.Store(false) diff --git a/conn_go18.go b/conn_go18.go index 8cab67c9d..2b9a9599e 100644 --- a/conn_go18.go +++ b/conn_go18.go @@ -129,7 +129,16 @@ func (cn *conn) watchCancel(ctx context.Context) func() { } func (cn *conn) cancel(ctx context.Context) error { - c, err := dial(ctx, cn.dialer, cn.opts) + // Create a new values map (copy). This makes sure the connection created + // in this method cannot write to the same underlying data, which could + // cause a concurrent map write panic. This is necessary because cancel + // is called from a goroutine in watchCancel. + o := make(values) + for k, v := range cn.opts { + o[k] = v + } + + c, err := dial(ctx, cn.dialer, o) if err != nil { return err } @@ -142,7 +151,7 @@ func (cn *conn) cancel(ctx context.Context) error { c: c, bad: bad, } - err = can.ssl(cn.opts) + err = can.ssl(o) if err != nil { return err } From 69b14f136170013aee4b2adb9b0291677770b01a Mon Sep 17 00:00:00 2001 From: Bjorn <47388782+bjornouderoelink@users.noreply.github.com> Date: Mon, 19 Apr 2021 21:51:42 +0200 Subject: [PATCH 4/4] Fix sslinline for connections after the first one. The sslinline functionality would delete the required keys after upgrading the first connection. This commit adds the sslinine key to the isDriverSetting so that it is not sent to Posgres which would cause a crash. It also removes the delete of the keys necessary for sslinline to allow SSL upgrades for connections after the first one. --- conn.go | 2 +- ssl.go | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/conn.go b/conn.go index 4f35614f3..b09a17047 100644 --- a/conn.go +++ b/conn.go @@ -1106,7 +1106,7 @@ func isDriverSetting(key string) bool { return true case "password": return true - case "sslmode", "sslcert", "sslkey", "sslrootcert": + case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline": return true case "fallback_application_name": return true diff --git a/ssl.go b/ssl.go index 881c2219b..e5eb92895 100644 --- a/ssl.go +++ b/ssl.go @@ -59,9 +59,6 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) { return nil, err } - // This pseudo-parameter is not recognized by the PostgreSQL server, so let's delete it after use. - delete(o, "sslinline") - // Accept renegotiation requests initiated by the backend. // // Renegotiation was deprecated then removed from PostgreSQL 9.5, but @@ -89,9 +86,6 @@ func sslClientCertificates(tlsConf *tls.Config, o values) error { sslinline := o["sslinline"] if sslinline == "true" { cert, err := tls.X509KeyPair([]byte(o["sslcert"]), []byte(o["sslkey"])) - // Clear out these params, in case they were to be sent to the PostgreSQL server by mistake - o["sslcert"] = "" - o["sslkey"] = "" if err != nil { return err } @@ -157,8 +151,6 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) error { var cert []byte if sslinline == "true" { - // // Clear out this param, in case it were to be sent to the PostgreSQL server by mistake - o["sslrootcert"] = "" cert = []byte(sslrootcert) } else { var err error