Home | History | Annotate | Download | only in report
      1 // Copyright 2015 syzkaller project authors. All rights reserved.
      2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
      3 
      4 package report
      5 
      6 import (
      7 	"fmt"
      8 	"testing"
      9 
     10 	"github.com/google/syzkaller/pkg/mgrconfig"
     11 	"github.com/google/syzkaller/pkg/symbolizer"
     12 )
     13 
     14 func TestLinuxIgnores(t *testing.T) {
     15 	cfg := &mgrconfig.Config{
     16 		TargetOS: "linux",
     17 	}
     18 	reporter, err := NewReporter(cfg)
     19 	if err != nil {
     20 		t.Fatal(err)
     21 	}
     22 	cfg.Ignores = []string{"BUG: bug3"}
     23 	reporter1, err := NewReporter(cfg)
     24 	if err != nil {
     25 		t.Fatal(err)
     26 	}
     27 	cfg.Ignores = []string{"BUG: bug3", "BUG: bug1"}
     28 	reporter2, err := NewReporter(cfg)
     29 	if err != nil {
     30 		t.Fatal(err)
     31 	}
     32 	cfg.Ignores = []string{"BUG: bug3", "BUG: bug1", "BUG: bug2"}
     33 	reporter3, err := NewReporter(cfg)
     34 	if err != nil {
     35 		t.Fatal(err)
     36 	}
     37 
     38 	const log = `
     39 [    0.000000] BUG: bug1
     40 [    0.000000] BUG: bug2
     41 	`
     42 	if !reporter.ContainsCrash([]byte(log)) {
     43 		t.Fatalf("no crash")
     44 	}
     45 	if rep := reporter.Parse([]byte(log)); rep.Title != "BUG: bug1" {
     46 		t.Fatalf("want `BUG: bug1`, found `%v`", rep.Title)
     47 	}
     48 
     49 	if !reporter1.ContainsCrash([]byte(log)) {
     50 		t.Fatalf("no crash")
     51 	}
     52 	if rep := reporter1.Parse([]byte(log)); rep.Title != "BUG: bug1" {
     53 		t.Fatalf("want `BUG: bug1`, found `%v`", rep.Title)
     54 	}
     55 
     56 	if !reporter2.ContainsCrash([]byte(log)) {
     57 		t.Fatalf("no crash")
     58 	}
     59 	if rep := reporter2.Parse([]byte(log)); rep.Title != "BUG: bug2" {
     60 		t.Fatalf("want `BUG: bug2`, found `%v`", rep.Title)
     61 	}
     62 
     63 	if reporter3.ContainsCrash([]byte(log)) {
     64 		t.Fatalf("found crash, should be ignored")
     65 	}
     66 	if rep := reporter3.Parse([]byte(log)); rep != nil {
     67 		t.Fatalf("found `%v`, should be ignored", rep.Title)
     68 	}
     69 }
     70 
     71 func TestLinuxSymbolizeLine(t *testing.T) {
     72 	tests := []struct {
     73 		line   string
     74 		result string
     75 	}{
     76 		// Normal symbolization.
     77 		{
     78 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x101/0x185\n",
     79 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x101/0x185 foo.c:555\n",
     80 		},
     81 		{
     82 			"RIP: 0010:[<ffffffff8188c0e6>]  [<ffffffff8188c0e6>]  foo+0x101/0x185\n",
     83 			"RIP: 0010:[<ffffffff8188c0e6>]  [<ffffffff8188c0e6>]  foo+0x101/0x185 foo.c:555\n",
     84 		},
     85 		// Strip "./" file prefix.
     86 		{
     87 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x111/0x185\n",
     88 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x111/0x185 foo.h:111\n",
     89 		},
     90 		// Needs symbolization, but symbolizer returns nothing.
     91 		{
     92 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x121/0x185\n",
     93 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x121/0x185\n",
     94 		},
     95 		// Needs symbolization, but symbolizer returns error.
     96 		{
     97 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x131/0x185\n",
     98 			"[ 2713.153531]  [<ffffffff82d1b1d9>] foo+0x131/0x185\n",
     99 		},
    100 		// Needs symbolization, but symbol is missing.
    101 		{
    102 			"[ 2713.153531]  [<ffffffff82d1b1d9>] bar+0x131/0x185\n",
    103 			"[ 2713.153531]  [<ffffffff82d1b1d9>] bar+0x131/0x185\n",
    104 		},
    105 		// Bad offset.
    106 		{
    107 			"[ 2713.153531]  [<ffffffff82d1b1d9>] bar+0xffffffffffffffffffff/0x185\n",
    108 			"[ 2713.153531]  [<ffffffff82d1b1d9>] bar+0xffffffffffffffffffff/0x185\n",
    109 		},
    110 		// Should not be symbolized.
    111 		{
    112 			"WARNING: CPU: 2 PID: 2636 at ipc/shm.c:162 foo+0x101/0x185\n",
    113 			"WARNING: CPU: 2 PID: 2636 at ipc/shm.c:162 foo+0x101/0x185 foo.c:555\n",
    114 		},
    115 		// Tricky function name.
    116 		{
    117 			"    [<ffffffff84e5bea0>] do_ipv6_setsockopt.isra.7.part.3+0x101/0x2830 \n",
    118 			"    [<ffffffff84e5bea0>] do_ipv6_setsockopt.isra.7.part.3+0x101/0x2830 net.c:111 \n",
    119 		},
    120 		// Old KASAN frame format (with tab).
    121 		{
    122 			"[   50.419727] 	baz+0x101/0x200\n",
    123 			"[   50.419727] 	baz+0x101/0x200 baz.c:100\n",
    124 		},
    125 		// Inlined frames.
    126 		{
    127 			"    [<ffffffff84e5bea0>] foo+0x141/0x185\n",
    128 			"    [<ffffffff84e5bea0>] inlined1 net.c:111 [inline]\n" +
    129 				"    [<ffffffff84e5bea0>] inlined2 mm.c:222 [inline]\n" +
    130 				"    [<ffffffff84e5bea0>] foo+0x141/0x185 kasan.c:333\n",
    131 		},
    132 		// Several symbols with the same name.
    133 		{
    134 			"[<ffffffff82d1b1d9>] baz+0x101/0x200\n",
    135 			"[<ffffffff82d1b1d9>] baz+0x101/0x200 baz.c:100\n",
    136 		},
    137 	}
    138 	symbols := map[string][]symbolizer.Symbol{
    139 		"foo": {
    140 			{Addr: 0x1000000, Size: 0x190},
    141 		},
    142 		"do_ipv6_setsockopt.isra.7.part.3": {
    143 			{Addr: 0x2000000, Size: 0x2830},
    144 		},
    145 		"baz": {
    146 			{Addr: 0x3000000, Size: 0x100},
    147 			{Addr: 0x4000000, Size: 0x200},
    148 			{Addr: 0x5000000, Size: 0x300},
    149 		},
    150 	}
    151 	symb := func(bin string, pc uint64) ([]symbolizer.Frame, error) {
    152 		if bin != "vmlinux" {
    153 			return nil, fmt.Errorf("unknown pc 0x%x", pc)
    154 		}
    155 		switch pc {
    156 		case 0x1000100:
    157 			return []symbolizer.Frame{
    158 				{
    159 					File: "/linux/foo.c",
    160 					Line: 555,
    161 				},
    162 			}, nil
    163 		case 0x1000110:
    164 			return []symbolizer.Frame{
    165 				{
    166 					File: "/linux/./foo.h",
    167 					Line: 111,
    168 				},
    169 			}, nil
    170 		case 0x1000120:
    171 			return nil, nil
    172 		case 0x1000130:
    173 			return nil, fmt.Errorf("unknown pc 0x%x", pc)
    174 		case 0x2000100:
    175 			return []symbolizer.Frame{
    176 				{
    177 					File: "/linux/net.c",
    178 					Line: 111,
    179 				},
    180 			}, nil
    181 		case 0x1000140:
    182 			return []symbolizer.Frame{
    183 				{
    184 					Func:   "inlined1",
    185 					File:   "/linux/net.c",
    186 					Line:   111,
    187 					Inline: true,
    188 				},
    189 				{
    190 					Func:   "inlined2",
    191 					File:   "/linux/mm.c",
    192 					Line:   222,
    193 					Inline: true,
    194 				},
    195 				{
    196 					Func:   "noninlined3",
    197 					File:   "/linux/kasan.c",
    198 					Line:   333,
    199 					Inline: false,
    200 				},
    201 			}, nil
    202 		case 0x4000100:
    203 			return []symbolizer.Frame{
    204 				{
    205 					File: "/linux/baz.c",
    206 					Line: 100,
    207 				},
    208 			}, nil
    209 		default:
    210 			return nil, fmt.Errorf("unknown pc 0x%x", pc)
    211 		}
    212 	}
    213 	for i, test := range tests {
    214 		t.Run(fmt.Sprint(i), func(t *testing.T) {
    215 			result := symbolizeLine(symb, symbols, "vmlinux", "/linux/", []byte(test.line))
    216 			if test.result != string(result) {
    217 				t.Errorf("want %q\n\t     get %q", test.result, string(result))
    218 			}
    219 		})
    220 	}
    221 }
    222