diff --git a/doc/go1.10.html b/doc/go1.10.html index fba4dcf190..9ea7325891 100644 --- a/doc/go1.10.html +++ b/doc/go1.10.html @@ -814,6 +814,13 @@ formats the X.509 distinguished name in the standard RFC 2253 format.
database/sql/driver

+Drivers that currently hold on to the destination buffer provdied by +driver.Rows.Next should ensure they no longer +write to a buffer assignedd to the destination array outside of that call. +Drivers must be careful that underlying buffers are not modified when closing +driver.Rows. +

+

Drivers that want to construct a sql.DB for their clients can now implement the Connector interface and call the new sql.OpenDB function, diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index 19a3a4f7c9..1e54b4cf2c 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -379,6 +379,10 @@ type Rows interface { // size as the Columns() are wide. // // Next should return io.EOF when there are no more rows. + // + // The dest should not be written to outside of Next. Care + // should be taken when closing Rows not to modify + // a buffer held in dest. Next(dest []Value) error } diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go index e795412de0..abb8d40fc0 100644 --- a/src/database/sql/fakedb_test.go +++ b/src/database/sql/fakedb_test.go @@ -1020,11 +1020,6 @@ func (rc *rowsCursor) touchMem() { } func (rc *rowsCursor) Close() error { - if !rc.closed { - for _, bs := range rc.bytesClone { - bs[0] = 255 // first byte corrupted - } - } rc.touchMem() rc.parentMem.touchMem() rc.closed = true diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index 8137eff82b..ae6bf7102e 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -663,43 +663,6 @@ func TestPoolExhaustOnCancel(t *testing.T) { } } -func TestByteOwnership(t *testing.T) { - db := newTestDB(t, "people") - defer closeDB(t, db) - rows, err := db.Query("SELECT|people|name,photo|") - if err != nil { - t.Fatalf("Query: %v", err) - } - type row struct { - name []byte - photo RawBytes - } - got := []row{} - for rows.Next() { - var r row - err = rows.Scan(&r.name, &r.photo) - if err != nil { - t.Fatalf("Scan: %v", err) - } - got = append(got, r) - } - corruptMemory := []byte("\xffPHOTO") - want := []row{ - {name: []byte("Alice"), photo: corruptMemory}, - {name: []byte("Bob"), photo: corruptMemory}, - {name: []byte("Chris"), photo: corruptMemory}, - } - if !reflect.DeepEqual(got, want) { - t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want) - } - - var photo RawBytes - err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo) - if err == nil { - t.Error("want error scanning into RawBytes from QueryRow") - } -} - func TestRowsColumns(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) @@ -3192,8 +3155,11 @@ func TestIssue18429(t *testing.T) { // reported. rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|") if rows != nil { + var name string // Call Next to test Issue 21117 and check for races. for rows.Next() { + // Scan the buffer so it is read and checked for races. + rows.Scan(&name) } rows.Close() }