浏览代码

Detect invalid addresses when parsing profile and report as error.

Alexey Alexandrov 8 年前
父节点
当前提交
236aa1ba21
共有 3 个文件被更改,包括 49 次插入26 次删除
  1. 7
    3
      profile/legacy_java_profile.go
  2. 27
    23
      profile/legacy_profile.go
  3. 15
    0
      profile/legacy_profile_test.go

+ 7
- 3
profile/legacy_java_profile.go 查看文件

178
 
178
 
179
 			// Java profiles have data/fields inverted compared to other
179
 			// Java profiles have data/fields inverted compared to other
180
 			// profile types.
180
 			// profile types.
181
-			value1, value2, addrs := sample[2], sample[1], sample[3]
181
+			var err error
182
+			value1, value2, value3 := sample[2], sample[1], sample[3]
183
+			addrs, err := parseHexAddresses(value3)
184
+			if err != nil {
185
+				return nil, nil, fmt.Errorf("malformed sample: %s: %v", line, err)
186
+			}
182
 
187
 
183
 			var sloc []*Location
188
 			var sloc []*Location
184
-			for _, addr := range parseHexAddresses(addrs) {
189
+			for _, addr := range addrs {
185
 				loc := locs[addr]
190
 				loc := locs[addr]
186
 				if locs[addr] == nil {
191
 				if locs[addr] == nil {
187
 					loc = &Location{
192
 					loc = &Location{
197
 				Location: sloc,
202
 				Location: sloc,
198
 			}
203
 			}
199
 
204
 
200
-			var err error
201
 			if s.Value[0], err = strconv.ParseInt(value1, 0, 64); err != nil {
205
 			if s.Value[0], err = strconv.ParseInt(value1, 0, 64); err != nil {
202
 				return nil, nil, fmt.Errorf("parsing sample %s: %v", line, err)
206
 				return nil, nil, fmt.Errorf("parsing sample %s: %v", line, err)
203
 			}
207
 			}

+ 27
- 23
profile/legacy_profile.go 查看文件

622
 		return nil, 0, nil, err
622
 		return nil, 0, nil, err
623
 	}
623
 	}
624
 
624
 
625
-	addrs = parseHexAddresses(sampleData[5])
625
+	addrs, err = parseHexAddresses(sampleData[5])
626
+	if err != nil {
627
+		return nil, 0, nil, fmt.Errorf("malformed sample: %s: %v", line, err)
628
+	}
626
 
629
 
627
 	return value, blocksize, addrs, nil
630
 	return value, blocksize, addrs, nil
628
 }
631
 }
629
 
632
 
630
-// extractHexAddresses extracts hex numbers from a string and returns
631
-// them, together with their numeric value, in a slice.
632
-func extractHexAddresses(s string) ([]string, []uint64) {
633
+// parseHexAddresses extracts hex numbers from a string, attempts to convert
634
+// each to an unsigned 64-bit number and returns the resulting numbers as a
635
+// slice, or an error if the string contains hex numbers which are too large to
636
+// handle (which means a malformed profile).
637
+func parseHexAddresses(s string) ([]uint64, error) {
633
 	hexStrings := hexNumberRE.FindAllString(s, -1)
638
 	hexStrings := hexNumberRE.FindAllString(s, -1)
634
-	var ids []uint64
639
+	var addrs []uint64
635
 	for _, s := range hexStrings {
640
 	for _, s := range hexStrings {
636
-		if id, err := strconv.ParseUint(s, 0, 64); err == nil {
637
-			ids = append(ids, id)
641
+		if addr, err := strconv.ParseUint(s, 0, 64); err == nil {
642
+			addrs = append(addrs, addr)
638
 		} else {
643
 		} else {
639
-			// Do not expect any parsing failures due to the regexp matching.
640
-			panic("failed to parse hex value:" + s)
644
+			return nil, fmt.Errorf("failed to parse as hex 64-bit number: %s", s)
641
 		}
645
 		}
642
 	}
646
 	}
643
-	return hexStrings, ids
644
-}
645
-
646
-// parseHexAddresses parses hex numbers from a string and returns them
647
-// in a slice.
648
-func parseHexAddresses(s string) []uint64 {
649
-	_, ids := extractHexAddresses(s)
650
-	return ids
647
+	return addrs, nil
651
 }
648
 }
652
 
649
 
653
 // scaleHeapSample adjusts the data from a heapz Sample to
650
 // scaleHeapSample adjusts the data from a heapz Sample to
803
 func parseContentionSample(line string, period, cpuHz int64) (value []int64, addrs []uint64, err error) {
800
 func parseContentionSample(line string, period, cpuHz int64) (value []int64, addrs []uint64, err error) {
804
 	sampleData := contentionSampleRE.FindStringSubmatch(line)
801
 	sampleData := contentionSampleRE.FindStringSubmatch(line)
805
 	if sampleData == nil {
802
 	if sampleData == nil {
806
-		return value, addrs, errUnrecognized
803
+		return nil, nil, errUnrecognized
807
 	}
804
 	}
808
 
805
 
809
 	v1, err := strconv.ParseInt(sampleData[1], 10, 64)
806
 	v1, err := strconv.ParseInt(sampleData[1], 10, 64)
810
 	if err != nil {
807
 	if err != nil {
811
-		return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
808
+		return nil, nil, fmt.Errorf("malformed sample: %s: %v", line, err)
812
 	}
809
 	}
813
 	v2, err := strconv.ParseInt(sampleData[2], 10, 64)
810
 	v2, err := strconv.ParseInt(sampleData[2], 10, 64)
814
 	if err != nil {
811
 	if err != nil {
815
-		return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
812
+		return nil, nil, fmt.Errorf("malformed sample: %s: %v", line, err)
816
 	}
813
 	}
817
 
814
 
818
 	// Unsample values if period and cpuHz are available.
815
 	// Unsample values if period and cpuHz are available.
827
 	}
824
 	}
828
 
825
 
829
 	value = []int64{v2, v1}
826
 	value = []int64{v2, v1}
830
-	addrs = parseHexAddresses(sampleData[3])
827
+	addrs, err = parseHexAddresses(sampleData[3])
828
+	if err != nil {
829
+		return nil, nil, fmt.Errorf("malformed sample: %s: %v", line, err)
830
+	}
831
 
831
 
832
 	return value, addrs, nil
832
 	return value, addrs, nil
833
 }
833
 }
872
 		var err error
872
 		var err error
873
 		line, addrs, err = parseThreadSample(s)
873
 		line, addrs, err = parseThreadSample(s)
874
 		if err != nil {
874
 		if err != nil {
875
-			return nil, errUnrecognized
875
+			return nil, err
876
 		}
876
 		}
877
 		if len(addrs) == 0 {
877
 		if len(addrs) == 0 {
878
 			// We got a --same as previous threads--. Bump counters.
878
 			// We got a --same as previous threads--. Bump counters.
936
 			continue
936
 			continue
937
 		}
937
 		}
938
 
938
 
939
-		addrs = append(addrs, parseHexAddresses(line)...)
939
+		curAddrs, err := parseHexAddresses(line)
940
+		if err != nil {
941
+			return "", nil, fmt.Errorf("malformed sample: %s: %v", line, err)
942
+		}
943
+		addrs = append(addrs, curAddrs...)
940
 	}
944
 	}
941
 	if err := s.Err(); err != nil {
945
 	if err := s.Err(); err != nil {
942
 		return "", nil, err
946
 		return "", nil, err

+ 15
- 0
profile/legacy_profile_test.go 查看文件

265
 	}
265
 	}
266
 }
266
 }
267
 
267
 
268
+func TestParseThreadProfileWithInvalidAddress(t *testing.T) {
269
+	profile := `
270
+--- threadz 1 ---
271
+
272
+--- Thread 7eff063d9940 (name: main/25376) stack: ---
273
+  PC: 0x40b688 0x4d5f51 0x40be31 0x473add693e639c6f0
274
+--- Memory map: ---
275
+  00400000-00fcb000: /home/rsilvera/cppbench/cppbench_server_main.unstripped
276
+	`
277
+	wantErr := "failed to parse as hex 64-bit number: 0x473add693e639c6f0"
278
+	if _, gotErr := parseThread([]byte(profile)); !strings.Contains(gotErr.Error(), wantErr) {
279
+		t.Errorf("parseThread(): got error %q, want error containing %q", gotErr, wantErr)
280
+	}
281
+}
282
+
268
 func TestParseGoCount(t *testing.T) {
283
 func TestParseGoCount(t *testing.T) {
269
 	for _, test := range []struct {
284
 	for _, test := range []struct {
270
 		in  string
285
 		in  string