1 // Copyright 2017 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 email 5 6 import ( 7 "fmt" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/google/go-cmp/cmp" 13 ) 14 15 func TestExtractCommand(t *testing.T) { 16 for i, test := range extractCommandTests { 17 t.Run(fmt.Sprint(i), func(t *testing.T) { 18 cmd, args := extractCommand([]byte(test.body)) 19 if cmd != test.cmd || !reflect.DeepEqual(args, test.args) { 20 t.Logf("expect: %q %q", test.cmd, test.args) 21 t.Logf("got : %q %q", cmd, args) 22 t.Fail() 23 } 24 cmd, args = extractCommand([]byte(strings.Replace(test.body, "\n", "\r\n", -1))) 25 if cmd != test.cmd || !reflect.DeepEqual(args, test.args) { 26 t.Logf("expect: %q %q", test.cmd, test.args) 27 t.Logf("got : %q %q", cmd, args) 28 t.Fail() 29 } 30 }) 31 } 32 } 33 34 func TestAddRemoveAddrContext(t *testing.T) { 35 email := `"Foo Bar" <foo (a] bar.com>` 36 email00, context00, err := RemoveAddrContext(email) 37 if err != nil { 38 t.Fatal(err) 39 } 40 if email != email00 { 41 t.Fatalf("want: %q, got %q", email, email00) 42 } 43 if context00 != "" { 44 t.Fatalf("want context: %q, got %q", "", context00) 45 } 46 context1 := "context1" 47 email1, err := AddAddrContext(email, context1) 48 if err != nil { 49 t.Fatal(err) 50 } 51 want1 := `"Foo Bar" <foo+context1 (a] bar.com>` 52 if want1 != email1 { 53 t.Fatalf("want: %q, got %q", want1, email1) 54 } 55 context2 := "context2" 56 email2, err := AddAddrContext(email1, context2) 57 if err != nil { 58 t.Fatal(err) 59 } 60 want2 := `"Foo Bar" <foo+context1+context2 (a] bar.com>` 61 if want2 != email2 { 62 t.Fatalf("want: %q, got %q", want2, email2) 63 } 64 email1, context20, err := RemoveAddrContext(email2) 65 if err != nil { 66 t.Fatal(err) 67 } 68 if want1 != email1 { 69 t.Fatalf("want: %q, got %q", want1, email1) 70 } 71 if context2 != context20 { 72 t.Fatalf("want context: %q, got %q", context2, context20) 73 } 74 email0, context10, err := RemoveAddrContext(email1) 75 if err != nil { 76 t.Fatal(err) 77 } 78 if email != email0 { 79 t.Fatalf("want: %q, got %q", email, email0) 80 } 81 if context1 != context10 { 82 t.Fatalf("want context: %q, got %q", context1, context10) 83 } 84 } 85 86 func TestAddAddrContextEmptyName(t *testing.T) { 87 email := "<foo (a] bar.com>" 88 email1, err := AddAddrContext(email, "context") 89 if err != nil { 90 t.Fatal(err) 91 } 92 if want := "foo+context (a] bar.com"; want != email1 { 93 t.Fatalf("want: %q, got %q", want, email1) 94 } 95 email2, context1, err := RemoveAddrContext(email1) 96 if err != nil { 97 t.Fatal(err) 98 } 99 if email != email2 { 100 t.Fatalf("want: %q, got %q", email, email2) 101 } 102 if context1 != "context" { 103 t.Fatalf("got context %q", context1) 104 } 105 } 106 107 func TestCanonicalEmail(t *testing.T) { 108 canonical := "foo (a] bar.com" 109 emails := []string{ 110 "\"Foo Bar\" <foo+123+456 (a] Bar.com>", 111 "<Foo (a] bar.com>", 112 } 113 for _, email := range emails { 114 if got := CanonicalEmail(email); got != canonical { 115 t.Errorf("got %q, want %q", got, canonical) 116 } 117 } 118 } 119 120 func TestParse(t *testing.T) { 121 for i, test := range parseTests { 122 body := func(t *testing.T, test ParseTest) { 123 email, err := Parse(strings.NewReader(test.email), []string{"bot <foo (a] bar.com>"}) 124 if err != nil { 125 t.Fatal(err) 126 } 127 if diff := cmp.Diff(&test.res, email); diff != "" { 128 t.Error(diff) 129 } 130 } 131 t.Run(fmt.Sprint(i), func(t *testing.T) { body(t, test) }) 132 133 test.email = strings.Replace(test.email, "\n", "\r\n", -1) 134 test.res.Body = strings.Replace(test.res.Body, "\n", "\r\n", -1) 135 t.Run(fmt.Sprint(i)+"rn", func(t *testing.T) { body(t, test) }) 136 } 137 } 138 139 var extractCommandTests = []struct { 140 body string 141 cmd string 142 args string 143 }{ 144 { 145 body: `Hello, 146 147 line1 148 #syz fix: bar baz `, 149 cmd: "fix:", 150 args: "bar baz", 151 }, 152 { 153 body: `Hello, 154 155 line1 156 #syz fix: bar baz 157 line 2 158 `, 159 cmd: "fix:", 160 args: "bar baz", 161 }, 162 { 163 body: ` 164 line1 165 > #syz fix: bar baz 166 line 2 167 `, 168 cmd: "", 169 args: "", 170 }, 171 // This is unfortunate case when a command is split by email client 172 // due to 80-column limitation. 173 { 174 body: ` 175 #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 176 locking/core 177 `, 178 cmd: "test:", 179 args: "git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core", 180 }, 181 { 182 body: ` 183 #syz test: 184 git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core 185 `, 186 cmd: "test:", 187 args: "git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core", 188 }, 189 { 190 body: ` 191 #syz test: 192 git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 193 locking/core 194 locking/core 195 `, 196 cmd: "test:", 197 args: "git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core", 198 }, 199 { 200 body: ` 201 #syz test_5_arg_cmd arg1 202 203 arg2 arg3 204 205 arg4 206 arg5 207 `, 208 cmd: "test_5_arg_cmd", 209 args: "arg1 arg2 arg3 arg4 arg5", 210 }, 211 { 212 body: ` 213 #syz test_5_arg_cmd arg1 214 arg2`, 215 cmd: "test_5_arg_cmd", 216 args: "arg1 arg2", 217 }, 218 { 219 body: ` 220 #syz test_5_arg_cmd arg1 221 arg2 222 `, 223 cmd: "test_5_arg_cmd", 224 args: "arg1 arg2", 225 }, 226 { 227 body: ` 228 #syz test_5_arg_cmd arg1 229 arg2 230 231 232 `, 233 cmd: "test_5_arg_cmd", 234 args: "arg1 arg2", 235 }, 236 { 237 body: ` 238 #syz fix: 239 arg1 arg2 arg3 240 arg4 arg5 241 242 `, 243 cmd: "fix:", 244 args: "arg1 arg2 arg3", 245 }, 246 { 247 body: ` 248 #syz fix: arg1 arg2 arg3 249 arg4 arg5 250 `, 251 cmd: "fix:", 252 args: "arg1 arg2 arg3", 253 }, 254 } 255 256 type ParseTest struct { 257 email string 258 res Email 259 } 260 261 // nolint: lll 262 var parseTests = []ParseTest{ 263 {`Date: Sun, 7 May 2017 19:54:00 -0700 264 Message-ID: <123> 265 Subject: test subject 266 From: Bob <bob (a] example.com> 267 To: syzbot <foo+4564456 (a] bar.com> 268 Content-Type: text/plain; charset="UTF-8" 269 270 text body 271 second line 272 #syz fix: arg1 arg2 arg3 273 last line 274 -- 275 You received this message because you are subscribed to the Google Groups "syzkaller" group. 276 To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller+unsubscribe (a] googlegroups.com. 277 To post to this group, send email to syzkaller (a] googlegroups.com. 278 To view this discussion on the web visit https://groups.google.com/d/msgid/syzkaller/abcdef@google.com. 279 For more options, visit https://groups.google.com/d/optout.`, 280 Email{ 281 BugID: "4564456", 282 MessageID: "<123>", 283 Link: "https://groups.google.com/d/msgid/syzkaller/abcdef@google.com", 284 Subject: "test subject", 285 From: "\"Bob\" <bob (a] example.com>", 286 Cc: []string{"bob (a] example.com"}, 287 Body: `text body 288 second line 289 #syz fix: arg1 arg2 arg3 290 last line 291 -- 292 You received this message because you are subscribed to the Google Groups "syzkaller" group. 293 To unsubscribe from this group and stop receiving emails from it, send an email to syzkaller+unsubscribe (a] googlegroups.com. 294 To post to this group, send email to syzkaller (a] googlegroups.com. 295 To view this discussion on the web visit https://groups.google.com/d/msgid/syzkaller/abcdef@google.com. 296 For more options, visit https://groups.google.com/d/optout.`, 297 Patch: "", 298 Command: "fix:", 299 CommandArgs: "arg1 arg2 arg3", 300 }}, 301 302 {`Date: Sun, 7 May 2017 19:54:00 -0700 303 Message-ID: <123> 304 Subject: test subject 305 From: syzbot <foo+4564456 (a] bar.com> 306 To: Bob <bob (a] example.com> 307 Content-Type: text/plain; charset="UTF-8" 308 309 text body 310 last line`, 311 Email{ 312 BugID: "4564456", 313 MessageID: "<123>", 314 Subject: "test subject", 315 From: "\"syzbot\" <foo+4564456 (a] bar.com>", 316 Cc: []string{"bob (a] example.com"}, 317 Body: `text body 318 last line`, 319 Patch: "", 320 }}, 321 322 {`Date: Sun, 7 May 2017 19:54:00 -0700 323 Message-ID: <123> 324 Subject: test subject 325 From: Bob <bob (a] example.com> 326 To: syzbot <bot (a] example.com>, Alice <alice (a] example.com> 327 328 #syz invalid 329 text body 330 second line 331 last line`, 332 Email{ 333 MessageID: "<123>", 334 Subject: "test subject", 335 From: "\"Bob\" <bob (a] example.com>", 336 Cc: []string{"alice (a] example.com", "bob (a] example.com", "bot (a] example.com"}, 337 Body: `#syz invalid 338 text body 339 second line 340 last line`, 341 Patch: "", 342 Command: "invalid", 343 CommandArgs: "", 344 }}, 345 346 {`Date: Sun, 7 May 2017 19:54:00 -0700 347 Message-ID: <123> 348 Subject: test subject 349 From: Bob <bob (a] example.com> 350 To: syzbot <bot (a] example.com>, Alice <alice (a] example.com> 351 Content-Type: text/plain 352 353 text body 354 second line 355 last line 356 #syz command`, 357 Email{ 358 MessageID: "<123>", 359 Subject: "test subject", 360 From: "\"Bob\" <bob (a] example.com>", 361 Cc: []string{"alice (a] example.com", "bob (a] example.com", "bot (a] example.com"}, 362 Body: `text body 363 second line 364 last line 365 #syz command`, 366 Patch: "", 367 Command: "command", 368 CommandArgs: "", 369 }}, 370 371 {`Date: Sun, 7 May 2017 19:54:00 -0700 372 Message-ID: <123> 373 Subject: test subject 374 From: Bob <bob (a] example.com> 375 To: syzbot <bot (a] example.com> 376 Content-Type: multipart/mixed; boundary="001a114ce0b01684a6054f0d8b81" 377 378 --001a114ce0b01684a6054f0d8b81 379 Content-Type: text/plain; charset="UTF-8" 380 381 body text 382 >#syz test 383 384 --001a114ce0b01684a6054f0d8b81 385 Content-Type: text/x-patch; charset="US-ASCII"; name="patch.patch" 386 Content-Disposition: attachment; filename="patch.patch" 387 Content-Transfer-Encoding: base64 388 X-Attachment-Id: f_j2gwcdoa1 389 390 ZGlmZiAtLWdpdCBhL2tlcm5lbC9rY292LmMgYi9rZXJuZWwva2Nvdi5jCmluZGV4IDg1ZTU1NDZj 391 ZDc5MS4uOTQ5ZWE0NTc0NDEyIDEwMDY0NAotLS0gYS9rZXJuZWwva2Nvdi5jCisrKyBiL2tlcm5l 392 bC9rY292LmMKQEAgLTEyNyw3ICsxMjcsNiBAQCB2b2lkIGtjb3ZfdGFza19leGl0KHN0cnVjdCB0 393 YXNrX3N0cnVjdCAqdCkKIAlrY292ID0gdC0+a2NvdjsKIAlpZiAoa2NvdiA9PSBOVUxMKQogCQly 394 ZXR1cm47Ci0Jc3Bpbl9sb2NrKCZrY292LT5sb2NrKTsKIAlpZiAoV0FSTl9PTihrY292LT50ICE9 395 IHQpKSB7CiAJCXNwaW5fdW5sb2NrKCZrY292LT5sb2NrKTsKIAkJcmV0dXJuOwo= 396 --001a114ce0b01684a6054f0d8b81--`, 397 Email{ 398 MessageID: "<123>", 399 Subject: "test subject", 400 From: "\"Bob\" <bob (a] example.com>", 401 Cc: []string{"bob (a] example.com", "bot (a] example.com"}, 402 Body: `body text 403 >#syz test 404 `, 405 Patch: `--- a/kernel/kcov.c 406 +++ b/kernel/kcov.c 407 @@ -127,7 +127,6 @@ void kcov_task_exit(struct task_struct *t) 408 kcov = t->kcov; 409 if (kcov == NULL) 410 return; 411 - spin_lock(&kcov->lock); 412 if (WARN_ON(kcov->t != t)) { 413 spin_unlock(&kcov->lock); 414 return; 415 `, 416 Command: "", 417 CommandArgs: "", 418 }}, 419 420 {`Date: Sun, 7 May 2017 19:54:00 -0700 421 Message-ID: <123> 422 Subject: test subject 423 From: Bob <bob (a] example.com> 424 To: syzbot <bot (a] example.com> 425 Content-Type: multipart/alternative; boundary="f403043eee70018593054f0d9f1f" 426 427 --f403043eee70018593054f0d9f1f 428 Content-Type: text/plain; charset="UTF-8" 429 430 On Mon, May 8, 2017 at 6:47 PM, Bob wrote: 431 > body text 432 433 #syz test 434 435 commit 59372bbf3abd5b24a7f6f676a3968685c280f955 436 Date: Thu Apr 27 13:54:11 2017 +0200 437 438 statx: correct error handling of NULL pathname 439 440 test patch. 441 442 diff --git a/fs/stat.c b/fs/stat.c 443 index 3d85747bd86e..a257b872a53d 100644 444 --- a/fs/stat.c 445 +++ b/fs/stat.c 446 @@ -567,8 +567,6 @@ SYSCALL_DEFINE5(statx, 447 return -EINVAL; 448 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) 449 return -EINVAL; 450 - if (!filename) 451 - return -EINVAL; 452 453 error = vfs_statx(dfd, filename, flags, &stat, mask); 454 if (error) 455 456 --f403043eee70018593054f0d9f1f 457 Content-Type: text/html; charset="UTF-8" 458 Content-Transfer-Encoding: quoted-printable 459 460 <div dir=3D"ltr">On Mon, May 8, 2017 at 6:47 PM, Dmitry Vyukov <<a href= 461 =3D"mailto:bob (a] example.com">bob (a] example.com</a>> wrote:<br>> bo= 462 dy text<br><br>#syz test<br><br><div><div>commit 59372bbf3abd5b24a7f6f67= 463 6a3968685c280f955</div><div>Date: =C2=A0 Thu Apr 27 13:54:11 2017 +0200</di= 464 v><div><br></div><div>=C2=A0 =C2=A0 statx: correct error handling of NULL p= 465 athname</div><div>=C2=A0 =C2=A0=C2=A0</div><div>=C2=A0 =C2=A0 test patch.</= 466 div><div><br></div><div>diff --git a/fs/stat.c b/fs/stat.c</div><div>index = 467 3d85747bd86e..a257b872a53d 100644</div><div>--- a/fs/stat.c</div><div>+++ b= 468 /fs/stat.c</div><div>@@ -567,8 +567,6 @@ SYSCALL_DEFINE5(statx,</div><div>= 469 =C2=A0<span class=3D"gmail-Apple-tab-span" style=3D"white-space:pre">=09=09= 470 </span>return -EINVAL;</div><div>=C2=A0<span class=3D"gmail-Apple-tab-span"= 471 style=3D"white-space:pre">=09</span>if ((flags & AT_STATX_SYNC_TYPE) = 472 =3D=3D AT_STATX_SYNC_TYPE)</div><div>=C2=A0<span class=3D"gmail-Apple-tab-s= 473 pan" style=3D"white-space:pre">=09=09</span>return -EINVAL;</div><div>-<spa= 474 n class=3D"gmail-Apple-tab-span" style=3D"white-space:pre">=09</span>if (!f= 475 ilename)</div><div>-<span class=3D"gmail-Apple-tab-span" style=3D"white-spa= 476 ce:pre">=09=09</span>return -EINVAL;</div><div>=C2=A0</div><div>=C2=A0<span= 477 class=3D"gmail-Apple-tab-span" style=3D"white-space:pre">=09</span>error = 478 =3D vfs_statx(dfd, filename, flags, &stat, mask);</div><div>=C2=A0<span= 479 class=3D"gmail-Apple-tab-span" style=3D"white-space:pre">=09</span>if (err= 480 or)</div></div></div> 481 482 --f403043eee70018593054f0d9f1f--`, 483 Email{ 484 MessageID: "<123>", 485 Subject: "test subject", 486 From: "\"Bob\" <bob (a] example.com>", 487 Cc: []string{"bob (a] example.com", "bot (a] example.com"}, 488 Body: `On Mon, May 8, 2017 at 6:47 PM, Bob wrote: 489 > body text 490 491 #syz test 492 493 commit 59372bbf3abd5b24a7f6f676a3968685c280f955 494 Date: Thu Apr 27 13:54:11 2017 +0200 495 496 statx: correct error handling of NULL pathname 497 498 test patch. 499 500 diff --git a/fs/stat.c b/fs/stat.c 501 index 3d85747bd86e..a257b872a53d 100644 502 --- a/fs/stat.c 503 +++ b/fs/stat.c 504 @@ -567,8 +567,6 @@ SYSCALL_DEFINE5(statx, 505 return -EINVAL; 506 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) 507 return -EINVAL; 508 - if (!filename) 509 - return -EINVAL; 510 511 error = vfs_statx(dfd, filename, flags, &stat, mask); 512 if (error) 513 `, 514 Patch: `--- a/fs/stat.c 515 +++ b/fs/stat.c 516 @@ -567,8 +567,6 @@ SYSCALL_DEFINE5(statx, 517 return -EINVAL; 518 if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE) 519 return -EINVAL; 520 - if (!filename) 521 - return -EINVAL; 522 523 error = vfs_statx(dfd, filename, flags, &stat, mask); 524 if (error) 525 `, 526 Command: "test", 527 CommandArgs: "", 528 }}, 529 530 {`Sender: syzkaller-bugs (a] googlegroups.com 531 Subject: Re: BUG: unable to handle kernel NULL pointer dereference in 532 sock_poll 533 To: syzbot <syzbot+344bb0f46d7719cd9483 (a] syzkaller.appspotmail.com> 534 From: bar <bar (a] foo.com> 535 Message-ID: <1250334f-7220-2bff-5d87-b87573758d81 (a] bar.com> 536 Date: Sun, 10 Jun 2018 10:38:20 +0900 537 MIME-Version: 1.0 538 Content-Type: text/plain; charset="UTF-8" 539 Content-Language: en-US 540 Content-Transfer-Encoding: quoted-printable 541 542 On 2018/06/10 4:57, syzbot wrote: 543 > Hello, 544 >=20 545 > syzbot found the following crash on: 546 >=20 547 > HEAD commit: 7d3bf613e99a Merge tag 'libnvdimm-for-4.18= 548 ' of git://git.k.. 549 > git tree: upstream 550 > console output: https://syzkaller.appspot.com/x/log.txt?x=3D1188a05f80000= 551 0 552 > kernel config: https://syzkaller.appspot.com/x/.config?x=3Df04d8d0a= 553 2afb789a 554 555 #syz dup: BUG: unable to handle kernel NULL pointer dereference in corrupte= 556 d 557 `, Email{ 558 MessageID: "<1250334f-7220-2bff-5d87-b87573758d81 (a] bar.com>", 559 Subject: "Re: BUG: unable to handle kernel NULL pointer dereference in sock_poll", 560 From: "\"bar\" <bar (a] foo.com>", 561 Cc: []string{"bar (a] foo.com", "syzbot (a] syzkaller.appspotmail.com"}, 562 Body: `On 2018/06/10 4:57, syzbot wrote: 563 > Hello, 564 > 565 > syzbot found the following crash on: 566 > 567 > HEAD commit: 7d3bf613e99a Merge tag 'libnvdimm-for-4.18' of git://git.k.. 568 > git tree: upstream 569 > console output: https://syzkaller.appspot.com/x/log.txt?x=1188a05f800000 570 > kernel config: https://syzkaller.appspot.com/x/.config?x=f04d8d0a2afb789a 571 572 #syz dup: BUG: unable to handle kernel NULL pointer dereference in corrupted 573 `, 574 Command: "dup:", 575 CommandArgs: "BUG: unable to handle kernel NULL pointer dereference in corrupted", 576 }}, 577 } 578