Changeset 0.22.0 (#93)
This commit is contained in:
@@ -183,3 +183,70 @@ func TestSafeJSON_PaginatedWithCorrupt(t *testing.T) {
|
||||
t.Fatalf("expected 500 for paginated response with corrupt item, got %d", w.Code)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Driver buffer aliasing tests ────────────
|
||||
// These verify the fix for the v0.21.7 corruption bug: scanJSON must
|
||||
// copy []byte from the database driver, not alias it. Without the copy,
|
||||
// rows.Next() can overwrite the buffer and corrupt previously-scanned
|
||||
// json.RawMessage values in a paginated list.
|
||||
|
||||
func TestScanJSON_ByteSliceNotAliased(t *testing.T) {
|
||||
var dest json.RawMessage
|
||||
s := scanJSON(&dest)
|
||||
|
||||
// Simulate driver buffer with valid JSON
|
||||
buf := []byte(`{"key":"value"}`)
|
||||
if err := s.Scan(buf); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Simulate driver reusing the buffer on next rows.Scan()
|
||||
copy(buf, []byte(`invalid_json!!`))
|
||||
|
||||
// dest must still hold the original valid value
|
||||
if !json.Valid(dest) {
|
||||
t.Fatalf("dest corrupted after source buffer reuse: %q", dest)
|
||||
}
|
||||
if string(dest) != `{"key":"value"}` {
|
||||
t.Fatalf("expected original value, got %q", dest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanJSON_ByteSliceIsolation_MultiRow(t *testing.T) {
|
||||
// Simulate scanning two rows through the same driver buffer,
|
||||
// as happens in ListChannels when lib/pq reuses memory.
|
||||
var dest1, dest2 json.RawMessage
|
||||
|
||||
// Row 1
|
||||
buf := make([]byte, 64)
|
||||
row1 := []byte(`{"row":1,"selector":"abc"}`)
|
||||
copy(buf, row1)
|
||||
s1 := scanJSON(&dest1)
|
||||
if err := s1.Scan(buf[:len(row1)]); err != nil {
|
||||
t.Fatalf("row 1 scan error: %v", err)
|
||||
}
|
||||
|
||||
// Row 2 — driver reuses same buffer
|
||||
row2 := []byte(`{"row":2}`)
|
||||
copy(buf, row2)
|
||||
s2 := scanJSON(&dest2)
|
||||
if err := s2.Scan(buf[:len(row2)]); err != nil {
|
||||
t.Fatalf("row 2 scan error: %v", err)
|
||||
}
|
||||
|
||||
// Both must retain their original values
|
||||
if string(dest1) != `{"row":1,"selector":"abc"}` {
|
||||
t.Fatalf("dest1 corrupted by row 2 scan: %q", dest1)
|
||||
}
|
||||
if string(dest2) != `{"row":2}` {
|
||||
t.Fatalf("dest2 unexpected value: %q", dest2)
|
||||
}
|
||||
|
||||
// Both must be independently valid JSON
|
||||
if !json.Valid(dest1) {
|
||||
t.Fatalf("dest1 not valid JSON after multi-row scan: %q", dest1)
|
||||
}
|
||||
if !json.Valid(dest2) {
|
||||
t.Fatalf("dest2 not valid JSON after multi-row scan: %q", dest2)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user