浏览代码

Detect concatenated profile and give clearer error message (#304)

This change detects concatenated profiles by checking if time_nanos appears more than once in the profile being parsed.

Fixes #273
Margaret Nolan 7 年前
父节点
当前提交
8cd90f1e63
共有 3 个文件被更改,包括 24 次插入2 次删除
  1. 6
    1
      profile/encode.go
  2. 2
    1
      profile/profile.go
  3. 16
    0
      profile/profile_test.go

+ 6
- 1
profile/encode.go 查看文件

214
 	// int64 keep_frames = 8
214
 	// int64 keep_frames = 8
215
 	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
215
 	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
216
 	// int64 time_nanos = 9
216
 	// int64 time_nanos = 9
217
-	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).TimeNanos) },
217
+	func(b *buffer, m message) error {
218
+		if m.(*Profile).TimeNanos != 0 {
219
+			return errConcatProfile
220
+		}
221
+		return decodeInt64(b, &m.(*Profile).TimeNanos)
222
+	},
218
 	// int64 duration_nanos = 10
223
 	// int64 duration_nanos = 10
219
 	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
224
 	func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
220
 	// ValueType period_type = 11
225
 	// ValueType period_type = 11

+ 2
- 1
profile/profile.go 查看文件

164
 			return nil, fmt.Errorf("decompressing profile: %v", err)
164
 			return nil, fmt.Errorf("decompressing profile: %v", err)
165
 		}
165
 		}
166
 	}
166
 	}
167
-	if p, err = ParseUncompressed(data); err != nil && err != errNoData {
167
+	if p, err = ParseUncompressed(data); err != nil && err != errNoData && err != errConcatProfile {
168
 		p, err = parseLegacy(data)
168
 		p, err = parseLegacy(data)
169
 	}
169
 	}
170
 
170
 
181
 var errUnrecognized = fmt.Errorf("unrecognized profile format")
181
 var errUnrecognized = fmt.Errorf("unrecognized profile format")
182
 var errMalformed = fmt.Errorf("malformed profile format")
182
 var errMalformed = fmt.Errorf("malformed profile format")
183
 var errNoData = fmt.Errorf("empty input file")
183
 var errNoData = fmt.Errorf("empty input file")
184
+var errConcatProfile = fmt.Errorf("concatenated profiles detected")
184
 
185
 
185
 func parseLegacy(data []byte) (*Profile, error) {
186
 func parseLegacy(data []byte) (*Profile, error) {
186
 	parsers := []func([]byte) (*Profile, error){
187
 	parsers := []func([]byte) (*Profile, error){

+ 16
- 0
profile/profile_test.go 查看文件

108
 	}
108
 	}
109
 }
109
 }
110
 
110
 
111
+func TestParseConcatentated(t *testing.T) {
112
+	prof := testProfile1.Copy()
113
+	// Write the profile twice to buffer to create concatented profile.
114
+	buf := bytes.NewBuffer(nil)
115
+	prof.Write(buf)
116
+	prof.Write(buf)
117
+	_, err := Parse(buf)
118
+	if err == nil {
119
+		t.Fatalf("got nil, want error")
120
+	}
121
+	if got, want := err.Error(), "parsing profile: concatenated profiles detected"; want != got {
122
+		t.Fatalf("got error %q, want error %q", got, want)
123
+	}
124
+}
125
+
111
 func TestCheckValid(t *testing.T) {
126
 func TestCheckValid(t *testing.T) {
112
 	const path = "testdata/java.cpu"
127
 	const path = "testdata/java.cpu"
113
 
128
 
276
 }
291
 }
277
 
292
 
278
 var testProfile1 = &Profile{
293
 var testProfile1 = &Profile{
294
+	TimeNanos:     10000,
279
 	PeriodType:    &ValueType{Type: "cpu", Unit: "milliseconds"},
295
 	PeriodType:    &ValueType{Type: "cpu", Unit: "milliseconds"},
280
 	Period:        1,
296
 	Period:        1,
281
 	DurationNanos: 10e9,
297
 	DurationNanos: 10e9,