slog: clip byte slice in commonHandler.clone

The clone method was failing to clip the preformattedAttrs field, a
[]byte, so the clone could affect the original.

This bug was discovered by Michael Lore.

Change-Id: I80e8fd9ca7e398272cae897520a36ac3a760cef7
Reviewed-on: https://go-review.googlesource.com/c/exp/+/449696
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
diff --git a/slog/handler.go b/slog/handler.go
index bc10a6b..e5216d1 100644
--- a/slog/handler.go
+++ b/slog/handler.go
@@ -165,7 +165,7 @@
 	return &commonHandler{
 		json:              h.json,
 		opts:              h.opts,
-		preformattedAttrs: h.preformattedAttrs,
+		preformattedAttrs: slices.Clip(h.preformattedAttrs),
 		groupPrefix:       h.groupPrefix,
 		groups:            slices.Clip(h.groups),
 		nOpenGroups:       h.nOpenGroups,
diff --git a/slog/handler_test.go b/slog/handler_test.go
index 0223cb8..41af25a 100644
--- a/slog/handler_test.go
+++ b/slog/handler_test.go
@@ -108,18 +108,6 @@
 	// remove all Attrs
 	removeAll := func(a Attr) Attr { return Attr{} }
 
-	// remove the given keys
-	removeKeys := func(keys ...string) func(a Attr) Attr {
-		return func(a Attr) Attr {
-			for _, k := range keys {
-				if a.Key == k {
-					return Attr{}
-				}
-			}
-			return a
-		}
-	}
-
 	attrs := []Attr{String("a", "one"), Int("b", 2), Any("", "ignore me")}
 	preAttrs := []Attr{Int("pre", 3), String("x", "y")}
 
@@ -303,6 +291,19 @@
 	}
 }
 
+// removeKeys returns a function suitable for HandlerOptions.ReplaceAttr
+// that removes all Attrs with the given keys.
+func removeKeys(keys ...string) func(a Attr) Attr {
+	return func(a Attr) Attr {
+		for _, k := range keys {
+			if a.Key == k {
+				return Attr{}
+			}
+		}
+		return a
+	}
+}
+
 func upperCaseKey(a Attr) Attr {
 	a.Key = strings.ToUpper(a.Key)
 	return a
@@ -371,6 +372,26 @@
 	}
 }
 
+func TestSecondWith(t *testing.T) {
+	// Verify that a second call to Logger.With does not corrupt
+	// the original.
+	var buf bytes.Buffer
+	h := HandlerOptions{ReplaceAttr: removeKeys(TimeKey)}.NewTextHandler(&buf)
+	logger := New(h).With(
+		String("app", "playground"),
+		String("role", "tester"),
+		Int("data_version", 2),
+	)
+	appLogger := logger.With("type", "log") // this becomes type=met
+	_ = logger.With("type", "metric")
+	appLogger.Info("foo")
+	got := strings.TrimSpace(buf.String())
+	want := `level=INFO msg=foo app=playground role=tester data_version=2 type=log`
+	if got != want {
+		t.Errorf("\ngot  %s\nwant %s", got, want)
+	}
+}
+
 const rfc3339Millis = "2006-01-02T15:04:05.000Z07:00"
 
 func TestWriteTimeRFC3339(t *testing.T) {