golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/http2/hpack/hpack_test.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hpack 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 "fmt" 11 "math/rand" 12 "reflect" 13 "strings" 14 "testing" 15 "time" 16 ) 17 18 func (d *Decoder) mustAt(idx int) HeaderField { 19 if hf, ok := d.at(uint64(idx)); !ok { 20 panic(fmt.Sprintf("bogus index %d", idx)) 21 } else { 22 return hf 23 } 24 } 25 26 func TestDynamicTableAt(t *testing.T) { 27 d := NewDecoder(4096, nil) 28 at := d.mustAt 29 if got, want := at(2), (pair(":method", "GET")); got != want { 30 t.Errorf("at(2) = %v; want %v", got, want) 31 } 32 d.dynTab.add(pair("foo", "bar")) 33 d.dynTab.add(pair("blake", "miz")) 34 if got, want := at(staticTable.len()+1), (pair("blake", "miz")); got != want { 35 t.Errorf("at(dyn 1) = %v; want %v", got, want) 36 } 37 if got, want := at(staticTable.len()+2), (pair("foo", "bar")); got != want { 38 t.Errorf("at(dyn 2) = %v; want %v", got, want) 39 } 40 if got, want := at(3), (pair(":method", "POST")); got != want { 41 t.Errorf("at(3) = %v; want %v", got, want) 42 } 43 } 44 45 func TestDynamicTableSizeEvict(t *testing.T) { 46 d := NewDecoder(4096, nil) 47 if want := uint32(0); d.dynTab.size != want { 48 t.Fatalf("size = %d; want %d", d.dynTab.size, want) 49 } 50 add := d.dynTab.add 51 add(pair("blake", "eats pizza")) 52 if want := uint32(15 + 32); d.dynTab.size != want { 53 t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want) 54 } 55 add(pair("foo", "bar")) 56 if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want { 57 t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want) 58 } 59 d.dynTab.setMaxSize(15 + 32 + 1 /* slop */) 60 if want := uint32(6 + 32); d.dynTab.size != want { 61 t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want) 62 } 63 if got, want := d.mustAt(staticTable.len()+1), (pair("foo", "bar")); got != want { 64 t.Errorf("at(dyn 1) = %v; want %v", got, want) 65 } 66 add(pair("long", strings.Repeat("x", 500))) 67 if want := uint32(0); d.dynTab.size != want { 68 t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want) 69 } 70 } 71 72 func TestDecoderDecode(t *testing.T) { 73 tests := []struct { 74 name string 75 in []byte 76 want []HeaderField 77 wantDynTab []HeaderField // newest entry first 78 }{ 79 // C.2.1 Literal Header Field with Indexing 80 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1 81 {"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"), 82 []HeaderField{pair("custom-key", "custom-header")}, 83 []HeaderField{pair("custom-key", "custom-header")}, 84 }, 85 86 // C.2.2 Literal Header Field without Indexing 87 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2 88 {"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"), 89 []HeaderField{pair(":path", "/sample/path")}, 90 []HeaderField{}}, 91 92 // C.2.3 Literal Header Field never Indexed 93 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3 94 {"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"), 95 []HeaderField{{"password", "secret", true}}, 96 []HeaderField{}}, 97 98 // C.2.4 Indexed Header Field 99 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4 100 {"C.2.4", []byte("\x82"), 101 []HeaderField{pair(":method", "GET")}, 102 []HeaderField{}}, 103 } 104 for _, tt := range tests { 105 d := NewDecoder(4096, nil) 106 hf, err := d.DecodeFull(tt.in) 107 if err != nil { 108 t.Errorf("%s: %v", tt.name, err) 109 continue 110 } 111 if !reflect.DeepEqual(hf, tt.want) { 112 t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want) 113 } 114 gotDynTab := d.dynTab.reverseCopy() 115 if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) { 116 t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab) 117 } 118 } 119 } 120 121 func (dt *dynamicTable) reverseCopy() (hf []HeaderField) { 122 hf = make([]HeaderField, len(dt.table.ents)) 123 for i := range hf { 124 hf[i] = dt.table.ents[len(dt.table.ents)-1-i] 125 } 126 return 127 } 128 129 type encAndWant struct { 130 enc []byte 131 want []HeaderField 132 wantDynTab []HeaderField 133 wantDynSize uint32 134 } 135 136 // C.3 Request Examples without Huffman Coding 137 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.3 138 func TestDecodeC3_NoHuffman(t *testing.T) { 139 testDecodeSeries(t, 4096, []encAndWant{ 140 {dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"), 141 []HeaderField{ 142 pair(":method", "GET"), 143 pair(":scheme", "http"), 144 pair(":path", "/"), 145 pair(":authority", "www.example.com"), 146 }, 147 []HeaderField{ 148 pair(":authority", "www.example.com"), 149 }, 150 57, 151 }, 152 {dehex("8286 84be 5808 6e6f 2d63 6163 6865"), 153 []HeaderField{ 154 pair(":method", "GET"), 155 pair(":scheme", "http"), 156 pair(":path", "/"), 157 pair(":authority", "www.example.com"), 158 pair("cache-control", "no-cache"), 159 }, 160 []HeaderField{ 161 pair("cache-control", "no-cache"), 162 pair(":authority", "www.example.com"), 163 }, 164 110, 165 }, 166 {dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"), 167 []HeaderField{ 168 pair(":method", "GET"), 169 pair(":scheme", "https"), 170 pair(":path", "/index.html"), 171 pair(":authority", "www.example.com"), 172 pair("custom-key", "custom-value"), 173 }, 174 []HeaderField{ 175 pair("custom-key", "custom-value"), 176 pair("cache-control", "no-cache"), 177 pair(":authority", "www.example.com"), 178 }, 179 164, 180 }, 181 }) 182 } 183 184 // C.4 Request Examples with Huffman Coding 185 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.4 186 func TestDecodeC4_Huffman(t *testing.T) { 187 testDecodeSeries(t, 4096, []encAndWant{ 188 {dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"), 189 []HeaderField{ 190 pair(":method", "GET"), 191 pair(":scheme", "http"), 192 pair(":path", "/"), 193 pair(":authority", "www.example.com"), 194 }, 195 []HeaderField{ 196 pair(":authority", "www.example.com"), 197 }, 198 57, 199 }, 200 {dehex("8286 84be 5886 a8eb 1064 9cbf"), 201 []HeaderField{ 202 pair(":method", "GET"), 203 pair(":scheme", "http"), 204 pair(":path", "/"), 205 pair(":authority", "www.example.com"), 206 pair("cache-control", "no-cache"), 207 }, 208 []HeaderField{ 209 pair("cache-control", "no-cache"), 210 pair(":authority", "www.example.com"), 211 }, 212 110, 213 }, 214 {dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"), 215 []HeaderField{ 216 pair(":method", "GET"), 217 pair(":scheme", "https"), 218 pair(":path", "/index.html"), 219 pair(":authority", "www.example.com"), 220 pair("custom-key", "custom-value"), 221 }, 222 []HeaderField{ 223 pair("custom-key", "custom-value"), 224 pair("cache-control", "no-cache"), 225 pair(":authority", "www.example.com"), 226 }, 227 164, 228 }, 229 }) 230 } 231 232 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.5 233 // "This section shows several consecutive header lists, corresponding 234 // to HTTP responses, on the same connection. The HTTP/2 setting 235 // parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 236 // octets, causing some evictions to occur." 237 func TestDecodeC5_ResponsesNoHuff(t *testing.T) { 238 testDecodeSeries(t, 256, []encAndWant{ 239 {dehex(` 240 4803 3330 3258 0770 7269 7661 7465 611d 241 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 242 2032 303a 3133 3a32 3120 474d 546e 1768 243 7474 7073 3a2f 2f77 7777 2e65 7861 6d70 244 6c65 2e63 6f6d 245 `), 246 []HeaderField{ 247 pair(":status", "302"), 248 pair("cache-control", "private"), 249 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 250 pair("location", "https://www.example.com"), 251 }, 252 []HeaderField{ 253 pair("location", "https://www.example.com"), 254 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 255 pair("cache-control", "private"), 256 pair(":status", "302"), 257 }, 258 222, 259 }, 260 {dehex("4803 3330 37c1 c0bf"), 261 []HeaderField{ 262 pair(":status", "307"), 263 pair("cache-control", "private"), 264 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 265 pair("location", "https://www.example.com"), 266 }, 267 []HeaderField{ 268 pair(":status", "307"), 269 pair("location", "https://www.example.com"), 270 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 271 pair("cache-control", "private"), 272 }, 273 222, 274 }, 275 {dehex(` 276 88c1 611d 4d6f 6e2c 2032 3120 4f63 7420 277 3230 3133 2032 303a 3133 3a32 3220 474d 278 54c0 5a04 677a 6970 7738 666f 6f3d 4153 279 444a 4b48 514b 425a 584f 5157 454f 5049 280 5541 5851 5745 4f49 553b 206d 6178 2d61 281 6765 3d33 3630 303b 2076 6572 7369 6f6e 282 3d31 283 `), 284 []HeaderField{ 285 pair(":status", "200"), 286 pair("cache-control", "private"), 287 pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), 288 pair("location", "https://www.example.com"), 289 pair("content-encoding", "gzip"), 290 pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), 291 }, 292 []HeaderField{ 293 pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), 294 pair("content-encoding", "gzip"), 295 pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), 296 }, 297 215, 298 }, 299 }) 300 } 301 302 // https://httpwg.org/specs/rfc7541.html#rfc.section.C.6 303 // "This section shows the same examples as the previous section, but 304 // using Huffman encoding for the literal values. The HTTP/2 setting 305 // parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 306 // octets, causing some evictions to occur. The eviction mechanism 307 // uses the length of the decoded literal values, so the same 308 // evictions occurs as in the previous section." 309 func TestDecodeC6_ResponsesHuffman(t *testing.T) { 310 testDecodeSeries(t, 256, []encAndWant{ 311 {dehex(` 312 4882 6402 5885 aec3 771a 4b61 96d0 7abe 313 9410 54d4 44a8 2005 9504 0b81 66e0 82a6 314 2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8 315 e9ae 82ae 43d3 316 `), 317 []HeaderField{ 318 pair(":status", "302"), 319 pair("cache-control", "private"), 320 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 321 pair("location", "https://www.example.com"), 322 }, 323 []HeaderField{ 324 pair("location", "https://www.example.com"), 325 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 326 pair("cache-control", "private"), 327 pair(":status", "302"), 328 }, 329 222, 330 }, 331 {dehex("4883 640e ffc1 c0bf"), 332 []HeaderField{ 333 pair(":status", "307"), 334 pair("cache-control", "private"), 335 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 336 pair("location", "https://www.example.com"), 337 }, 338 []HeaderField{ 339 pair(":status", "307"), 340 pair("location", "https://www.example.com"), 341 pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"), 342 pair("cache-control", "private"), 343 }, 344 222, 345 }, 346 {dehex(` 347 88c1 6196 d07a be94 1054 d444 a820 0595 348 040b 8166 e084 a62d 1bff c05a 839b d9ab 349 77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b 350 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 351 9587 3160 65c0 03ed 4ee5 b106 3d50 07 352 `), 353 []HeaderField{ 354 pair(":status", "200"), 355 pair("cache-control", "private"), 356 pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), 357 pair("location", "https://www.example.com"), 358 pair("content-encoding", "gzip"), 359 pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), 360 }, 361 []HeaderField{ 362 pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"), 363 pair("content-encoding", "gzip"), 364 pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"), 365 }, 366 215, 367 }, 368 }) 369 } 370 371 func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) { 372 d := NewDecoder(size, nil) 373 for i, step := range steps { 374 hf, err := d.DecodeFull(step.enc) 375 if err != nil { 376 t.Fatalf("Error at step index %d: %v", i, err) 377 } 378 if !reflect.DeepEqual(hf, step.want) { 379 t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want) 380 } 381 gotDynTab := d.dynTab.reverseCopy() 382 if !reflect.DeepEqual(gotDynTab, step.wantDynTab) { 383 t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab) 384 } 385 if d.dynTab.size != step.wantDynSize { 386 t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize) 387 } 388 } 389 } 390 391 func TestHuffmanDecodeExcessPadding(t *testing.T) { 392 tests := [][]byte{ 393 {0xff}, // Padding Exceeds 7 bits 394 {0x1f, 0xff}, // {"a", 1 byte excess padding} 395 {0x1f, 0xff, 0xff}, // {"a", 2 byte excess padding} 396 {0x1f, 0xff, 0xff, 0xff}, // {"a", 3 byte excess padding} 397 {0xff, 0x9f, 0xff, 0xff, 0xff}, // {"a", 29 bit excess padding} 398 {'R', 0xbc, '0', 0xff, 0xff, 0xff, 0xff}, // Padding ends on partial symbol. 399 } 400 for i, in := range tests { 401 var buf bytes.Buffer 402 if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { 403 t.Errorf("test-%d: decode(%q) = %v; want ErrInvalidHuffman", i, in, err) 404 } 405 } 406 } 407 408 func TestHuffmanDecodeEOS(t *testing.T) { 409 in := []byte{0xff, 0xff, 0xff, 0xff, 0xfc} // {EOS, "?"} 410 var buf bytes.Buffer 411 if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { 412 t.Errorf("error = %v; want ErrInvalidHuffman", err) 413 } 414 } 415 416 func TestHuffmanDecodeMaxLengthOnTrailingByte(t *testing.T) { 417 in := []byte{0x00, 0x01} // {"0", "0", "0"} 418 var buf bytes.Buffer 419 if err := huffmanDecode(&buf, 2, in); err != ErrStringLength { 420 t.Errorf("error = %v; want ErrStringLength", err) 421 } 422 } 423 424 func TestHuffmanDecodeCorruptPadding(t *testing.T) { 425 in := []byte{0x00} 426 var buf bytes.Buffer 427 if _, err := HuffmanDecode(&buf, in); err != ErrInvalidHuffman { 428 t.Errorf("error = %v; want ErrInvalidHuffman", err) 429 } 430 } 431 432 func TestHuffmanDecode(t *testing.T) { 433 tests := []struct { 434 inHex, want string 435 }{ 436 {"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"}, 437 {"a8eb 1064 9cbf", "no-cache"}, 438 {"25a8 49e9 5ba9 7d7f", "custom-key"}, 439 {"25a8 49e9 5bb8 e8b4 bf", "custom-value"}, 440 {"6402", "302"}, 441 {"aec3 771a 4b", "private"}, 442 {"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"}, 443 {"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"}, 444 {"9bd9 ab", "gzip"}, 445 {"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07", 446 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, 447 } 448 for i, tt := range tests { 449 var buf bytes.Buffer 450 in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1)) 451 if err != nil { 452 t.Errorf("%d. hex input error: %v", i, err) 453 continue 454 } 455 if _, err := HuffmanDecode(&buf, in); err != nil { 456 t.Errorf("%d. decode error: %v", i, err) 457 continue 458 } 459 if got := buf.String(); tt.want != got { 460 t.Errorf("%d. decode = %q; want %q", i, got, tt.want) 461 } 462 } 463 } 464 465 func BenchmarkHuffmanDecode(b *testing.B) { 466 b.StopTimer() 467 enc, err := hex.DecodeString(strings.Replace("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07", 468 " ", "", -1)) 469 if err != nil { 470 b.Fatal(err) 471 } 472 b.ReportAllocs() 473 b.StartTimer() 474 var buf bytes.Buffer 475 for i := 0; i < b.N; i++ { 476 buf.Reset() 477 if _, err := HuffmanDecode(&buf, enc); err != nil { 478 b.Fatalf("decode error: %v", err) 479 } 480 if string(buf.Bytes()) != "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1" { 481 b.Fatalf("bogus output %q", buf.Bytes()) 482 } 483 } 484 } 485 486 func TestAppendHuffmanString(t *testing.T) { 487 tests := []struct { 488 in, want string 489 }{ 490 {"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"}, 491 {"no-cache", "a8eb 1064 9cbf"}, 492 {"custom-key", "25a8 49e9 5ba9 7d7f"}, 493 {"custom-value", "25a8 49e9 5bb8 e8b4 bf"}, 494 {"302", "6402"}, 495 {"private", "aec3 771a 4b"}, 496 {"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"}, 497 {"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"}, 498 {"gzip", "9bd9 ab"}, 499 {"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", 500 "94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"}, 501 } 502 for i, tt := range tests { 503 buf := []byte{} 504 want := strings.Replace(tt.want, " ", "", -1) 505 buf = AppendHuffmanString(buf, tt.in) 506 if got := hex.EncodeToString(buf); want != got { 507 t.Errorf("%d. encode = %q; want %q", i, got, want) 508 } 509 } 510 } 511 512 func BenchmarkAppendHuffmanString(b *testing.B) { 513 b.StopTimer() 514 expected, err := hex.DecodeString(strings.Replace("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07", 515 " ", "", -1)) 516 if err != nil { 517 b.Fatal(err) 518 } 519 buf := make([]byte, 0, len(expected)) 520 b.ReportAllocs() 521 b.StartTimer() 522 523 for i := 0; i < b.N; i++ { 524 enc := AppendHuffmanString(buf, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1") 525 if string(enc) != string(expected) { 526 b.Fatalf("bogus output %q", enc) 527 } 528 } 529 } 530 531 func TestHuffmanMaxStrLen(t *testing.T) { 532 const msg = "Some string" 533 huff := AppendHuffmanString(nil, msg) 534 535 testGood := func(max int) { 536 var out bytes.Buffer 537 if err := huffmanDecode(&out, max, huff); err != nil { 538 t.Errorf("For maxLen=%d, unexpected error: %v", max, err) 539 } 540 if out.String() != msg { 541 t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg) 542 } 543 } 544 testGood(0) 545 testGood(len(msg)) 546 testGood(len(msg) + 1) 547 548 var out bytes.Buffer 549 if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength { 550 t.Errorf("err = %v; want ErrStringLength", err) 551 } 552 } 553 554 func TestHuffmanRoundtripStress(t *testing.T) { 555 const Len = 50 // of uncompressed string 556 input := make([]byte, Len) 557 var output bytes.Buffer 558 var huff []byte 559 560 n := 5000 561 if testing.Short() { 562 n = 100 563 } 564 seed := time.Now().UnixNano() 565 t.Logf("Seed = %v", seed) 566 src := rand.New(rand.NewSource(seed)) 567 var encSize int64 568 for i := 0; i < n; i++ { 569 for l := range input { 570 input[l] = byte(src.Intn(256)) 571 } 572 huff = AppendHuffmanString(huff[:0], string(input)) 573 encSize += int64(len(huff)) 574 output.Reset() 575 if err := huffmanDecode(&output, 0, huff); err != nil { 576 t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err) 577 continue 578 } 579 if !bytes.Equal(output.Bytes(), input) { 580 t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes()) 581 } 582 } 583 t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize) 584 } 585 586 func TestHuffmanDecodeFuzz(t *testing.T) { 587 const Len = 50 // of compressed 588 var buf, zbuf bytes.Buffer 589 590 n := 5000 591 if testing.Short() { 592 n = 100 593 } 594 seed := time.Now().UnixNano() 595 t.Logf("Seed = %v", seed) 596 src := rand.New(rand.NewSource(seed)) 597 numFail := 0 598 for i := 0; i < n; i++ { 599 zbuf.Reset() 600 if i == 0 { 601 // Start with at least one invalid one. 602 zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8") 603 } else { 604 for l := 0; l < Len; l++ { 605 zbuf.WriteByte(byte(src.Intn(256))) 606 } 607 } 608 609 buf.Reset() 610 if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil { 611 if err == ErrInvalidHuffman { 612 numFail++ 613 continue 614 } 615 t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err) 616 continue 617 } 618 } 619 t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n) 620 if numFail < 1 { 621 t.Error("expected at least one invalid huffman encoding (test starts with one)") 622 } 623 } 624 625 func TestReadVarInt(t *testing.T) { 626 type res struct { 627 i uint64 628 consumed int 629 err error 630 } 631 tests := []struct { 632 n byte 633 p []byte 634 want res 635 }{ 636 // Fits in a byte: 637 {1, []byte{0}, res{0, 1, nil}}, 638 {2, []byte{2}, res{2, 1, nil}}, 639 {3, []byte{6}, res{6, 1, nil}}, 640 {4, []byte{14}, res{14, 1, nil}}, 641 {5, []byte{30}, res{30, 1, nil}}, 642 {6, []byte{62}, res{62, 1, nil}}, 643 {7, []byte{126}, res{126, 1, nil}}, 644 {8, []byte{254}, res{254, 1, nil}}, 645 646 // Doesn't fit in a byte: 647 {1, []byte{1}, res{0, 0, errNeedMore}}, 648 {2, []byte{3}, res{0, 0, errNeedMore}}, 649 {3, []byte{7}, res{0, 0, errNeedMore}}, 650 {4, []byte{15}, res{0, 0, errNeedMore}}, 651 {5, []byte{31}, res{0, 0, errNeedMore}}, 652 {6, []byte{63}, res{0, 0, errNeedMore}}, 653 {7, []byte{127}, res{0, 0, errNeedMore}}, 654 {8, []byte{255}, res{0, 0, errNeedMore}}, 655 656 // Ignoring top bits: 657 {5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111 658 {5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100 659 {5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101 660 661 // Extra byte: 662 {5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte 663 664 // Short a byte: 665 {5, []byte{191, 154}, res{0, 0, errNeedMore}}, 666 667 // integer overflow: 668 {1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}}, 669 } 670 for _, tt := range tests { 671 i, remain, err := readVarInt(tt.n, tt.p) 672 consumed := len(tt.p) - len(remain) 673 got := res{i, consumed, err} 674 if got != tt.want { 675 t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want) 676 } 677 } 678 } 679 680 // Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56 681 func TestHuffmanFuzzCrash(t *testing.T) { 682 got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8")) 683 if got != "" { 684 t.Errorf("Got %q; want empty string", got) 685 } 686 if err != ErrInvalidHuffman { 687 t.Errorf("Err = %v; want ErrInvalidHuffman", err) 688 } 689 } 690 691 func pair(name, value string) HeaderField { 692 return HeaderField{Name: name, Value: value} 693 } 694 695 func dehex(s string) []byte { 696 s = strings.Replace(s, " ", "", -1) 697 s = strings.Replace(s, "\n", "", -1) 698 b, err := hex.DecodeString(s) 699 if err != nil { 700 panic(err) 701 } 702 return b 703 } 704 705 func TestEmitEnabled(t *testing.T) { 706 var buf bytes.Buffer 707 enc := NewEncoder(&buf) 708 enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) 709 enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) 710 711 numCallback := 0 712 var dec *Decoder 713 dec = NewDecoder(8<<20, func(HeaderField) { 714 numCallback++ 715 dec.SetEmitEnabled(false) 716 }) 717 if !dec.EmitEnabled() { 718 t.Errorf("initial emit enabled = false; want true") 719 } 720 if _, err := dec.Write(buf.Bytes()); err != nil { 721 t.Error(err) 722 } 723 if numCallback != 1 { 724 t.Errorf("num callbacks = %d; want 1", numCallback) 725 } 726 if dec.EmitEnabled() { 727 t.Errorf("emit enabled = true; want false") 728 } 729 } 730 731 func TestSlowIncrementalDecode(t *testing.T) { 732 // TODO(dneil): Fix for -race mode. 733 t.Skip("too slow in -race mode") 734 735 var buf bytes.Buffer 736 enc := NewEncoder(&buf) 737 hf := HeaderField{ 738 Name: strings.Repeat("k", 1<<20), 739 Value: strings.Repeat("v", 1<<20), 740 } 741 enc.WriteField(hf) 742 hbuf := buf.Bytes() 743 count := 0 744 dec := NewDecoder(initialHeaderTableSize, func(got HeaderField) { 745 count++ 746 if count != 1 { 747 t.Errorf("decoded %v fields, want 1", count) 748 } 749 if got.Name != hf.Name { 750 t.Errorf("decoded Name does not match input") 751 } 752 if got.Value != hf.Value { 753 t.Errorf("decoded Value does not match input") 754 } 755 }) 756 for i := 0; i < len(hbuf); i++ { 757 dec.Write(hbuf[i : i+1]) 758 } 759 } 760 761 func TestSaveBufLimit(t *testing.T) { 762 const maxStr = 1 << 10 763 var got []HeaderField 764 dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) { 765 got = append(got, hf) 766 }) 767 dec.SetMaxStringLength(maxStr) 768 var frag []byte 769 frag = append(frag[:0], encodeTypeByte(false, false)) 770 frag = appendVarInt(frag, 7, 3) 771 frag = append(frag, "foo"...) 772 frag = appendVarInt(frag, 7, 3) 773 frag = append(frag, "bar"...) 774 775 if _, err := dec.Write(frag); err != nil { 776 t.Fatal(err) 777 } 778 779 want := []HeaderField{{Name: "foo", Value: "bar"}} 780 if !reflect.DeepEqual(got, want) { 781 t.Errorf("After small writes, got %v; want %v", got, want) 782 } 783 784 frag = append(frag[:0], encodeTypeByte(false, false)) 785 frag = appendVarInt(frag, 7, maxStr*3) 786 frag = append(frag, make([]byte, maxStr*3)...) 787 788 _, err := dec.Write(frag) 789 if err != ErrStringLength { 790 t.Fatalf("Write error = %v; want ErrStringLength", err) 791 } 792 } 793 794 func TestDynamicSizeUpdate(t *testing.T) { 795 var buf bytes.Buffer 796 enc := NewEncoder(&buf) 797 enc.SetMaxDynamicTableSize(255) 798 enc.WriteField(HeaderField{Name: "foo", Value: "bar"}) 799 800 d := NewDecoder(4096, func(_ HeaderField) {}) 801 _, err := d.Write(buf.Bytes()) 802 if err != nil { 803 t.Fatalf("unexpected error: got = %v", err) 804 } 805 806 d.Close() 807 808 // Start a new header 809 _, err = d.Write(buf.Bytes()) 810 if err != nil { 811 t.Fatalf("unexpected error: got = %v", err) 812 } 813 814 // must fail since the dynamic table update must be at the beginning 815 _, err = d.Write(buf.Bytes()) 816 if err == nil { 817 t.Fatalf("dynamic table size update not at the beginning of a header block") 818 } 819 }