Browse Source

fix(stackdriver adapter): strip bad utf8 in log text (#17114)

This PR checks log entry strings in stackdriver for illegal utf-8 runes and removes
them when discovered.
Douglas Reid 1 month ago
parent
commit
9e11075759
2 changed files with 38 additions and 3 deletions
  1. 19
    3
      mixer/adapter/stackdriver/log/log.go
  2. 19
    0
      mixer/adapter/stackdriver/log/log_test.go

+ 19
- 3
mixer/adapter/stackdriver/log/log.go View File

@@ -24,6 +24,7 @@ import (
24 24
 	"strings"
25 25
 	"text/template"
26 26
 	"time"
27
+	"unicode/utf8"
27 28
 
28 29
 	"cloud.google.com/go/logging"
29 30
 	"cloud.google.com/go/logging/logadmin"
@@ -226,20 +227,35 @@ func toLabelMap(names []string, variables map[string]interface{}, logEntryTypes
226 227
 		v := variables[name]
227 228
 		switch vt := v.(type) {
228 229
 		case string:
229
-			out[name] = vt
230
+			out[name] = stripBadUTF8(vt)
230 231
 		case []byte:
231 232
 			if logEntryTypes[name] == istio_policy_v1beta1.IP_ADDRESS {
232 233
 				out[name] = net.IP(vt).String()
233 234
 			} else {
234
-				out[name] = fmt.Sprintf("%v", vt)
235
+				out[name] = stripBadUTF8(fmt.Sprintf("%v", vt))
235 236
 			}
236 237
 		default:
237
-			out[name] = fmt.Sprintf("%v", vt)
238
+			out[name] = stripBadUTF8(fmt.Sprintf("%v", vt))
238 239
 		}
239 240
 	}
240 241
 	return out
241 242
 }
242 243
 
244
+func stripBadUTF8(input string) string {
245
+	if utf8.ValidString(input) {
246
+		return input
247
+	}
248
+
249
+	out := make([]rune, 0, len(input))
250
+	for _, r := range input {
251
+		if r == utf8.RuneError {
252
+			continue
253
+		}
254
+		out = append(out, r)
255
+	}
256
+	return string(out)
257
+}
258
+
243 259
 func toReq(mapping *config.Params_LogInfo_HttpRequestMapping, variables map[string]interface{}) *logging.HTTPRequest {
244 260
 	if mapping == nil {
245 261
 		return nil

+ 19
- 0
mixer/adapter/stackdriver/log/log_test.go View File

@@ -192,6 +192,25 @@ func TestHandleLogEntry(t *testing.T) {
192 192
 					},
193 193
 				},
194 194
 			}},
195
+		{"labels with bad utf8",
196
+			map[string]info{"labels": {tmpl: template.Must(template.New("").Parse("literal")), labels: []string{"foo", "time"}, log: log}},
197
+			[]*logentry.Instance{{Name: "labels", Variables: map[string]interface{}{"foo": "bar\xed\xa0\x80", "time": now}}},
198
+			[]logging.Entry{
199
+				{
200
+					Timestamp: now,
201
+					Severity:  logging.Default,
202
+					Labels:    map[string]string{"foo": "bar", "time": fmt.Sprintf("%v", now)},
203
+					Payload:   "literal",
204
+				},
205
+			},
206
+			map[string]*logentry.Type{
207
+				"labels": {
208
+					Variables: map[string]descriptor.ValueType{
209
+						"foo":  descriptor.STRING,
210
+						"time": descriptor.TIMESTAMP,
211
+					},
212
+				},
213
+			}},
195 214
 		{"labels only one",
196 215
 			map[string]info{"labels": {tmpl: template.Must(template.New("").Parse("literal")), labels: []string{"foo"}, log: log}},
197 216
 			[]*logentry.Instance{{Name: "labels", Variables: map[string]interface{}{"foo": "bar", "time": fmt.Sprintf("%v", now)}}},

Loading…
Cancel
Save