|
| 1 | +--TEST-- |
| 2 | +base64_decode() with whitespace, padding and invalid bytes inside the input, in both modes |
| 3 | +--FILE-- |
| 4 | +<?php |
| 5 | +$clean = base64_encode("The quick brown fox jumps over the lazy dog, 0123456789."); |
| 6 | + |
| 7 | +$inputs = [ |
| 8 | + 'clean' => $clean, |
| 9 | + 'leading and trailing whitespace' => " \t\r\n" . $clean . "\n\n", |
| 10 | + 'space inside a group' => substr($clean, 0, 2) . ' ' . substr($clean, 2), |
| 11 | + 'space between groups' => substr($clean, 0, 4) . ' ' . substr($clean, 4), |
| 12 | + 'a space after every character' => implode(' ', str_split($clean)), |
| 13 | + 'MIME lines' => chunk_split($clean, 76, "\r\n"), |
| 14 | + 'PEM lines' => chunk_split($clean, 64, "\n"), |
| 15 | + 'short lines' => chunk_split($clean, 7, "\n"), |
| 16 | + 'line break before the padding' => substr($clean, 0, -2) . "\n" . substr($clean, -2), |
| 17 | + 'line break inside the padding' => substr($clean, 0, -1) . "\n" . substr($clean, -1), |
| 18 | + 'line break after the padding' => $clean . "\n", |
| 19 | + 'no padding' => rtrim($clean, '='), |
| 20 | + 'no padding, trailing whitespace' => rtrim($clean, '=') . " \n", |
| 21 | + 'data after the padding' => $clean . 'QUJD', |
| 22 | + 'padding in the middle' => substr($clean, 0, 8) . '==' . substr($clean, 8), |
| 23 | + 'invalid byte inside a group' => substr($clean, 0, 2) . '*' . substr($clean, 2), |
| 24 | + 'invalid byte between groups' => substr($clean, 0, 4) . '-' . substr($clean, 4), |
| 25 | + 'high byte' => substr($clean, 0, 4) . "\xC3\xA9" . substr($clean, 4), |
| 26 | + 'one character' => 'Q', |
| 27 | + 'two characters' => 'QU', |
| 28 | + 'three characters' => 'QUJ', |
| 29 | + 'five characters' => 'QUJDR', |
| 30 | + 'only whitespace' => " \n\t", |
| 31 | + 'only padding' => '====', |
| 32 | + 'empty' => '', |
| 33 | +]; |
| 34 | + |
| 35 | +function show($result) { |
| 36 | + if ($result === false) { |
| 37 | + return 'false'; |
| 38 | + } |
| 39 | + $plain = ' .,' . implode('', range('0', '9')) . implode('', range('a', 'z')) . implode('', range('A', 'Z')); |
| 40 | + return strspn($result, $plain) === strlen($result) ? "'$result'" : 'bytes ' . bin2hex($result); |
| 41 | +} |
| 42 | + |
| 43 | +foreach ($inputs as $name => $input) { |
| 44 | + printf("%-34s %s | %s\n", $name, show(base64_decode($input)), show(base64_decode($input, true))); |
| 45 | +} |
| 46 | + |
| 47 | +// every length around the group and vector block boundaries, with a line break at every position |
| 48 | +$ok = true; |
| 49 | +for ($bytes = 0; $bytes <= 100; $bytes++) { |
| 50 | + $raw = $bytes ? random_bytes($bytes) : ""; |
| 51 | + $encoded = base64_encode($raw); |
| 52 | + for ($at = 0; $at <= strlen($encoded); $at++) { |
| 53 | + $broken = substr($encoded, 0, $at) . "\r\n" . substr($encoded, $at); |
| 54 | + if (base64_decode($broken) !== $raw || base64_decode($broken, true) !== $raw) { |
| 55 | + echo "mismatch: $bytes bytes, line break at $at\n"; |
| 56 | + $ok = false; |
| 57 | + } |
| 58 | + } |
| 59 | + $mime = chunk_split($encoded, 76, "\r\n"); |
| 60 | + if (base64_decode($mime) !== $raw || base64_decode($mime, true) !== $raw) { |
| 61 | + echo "mismatch: $bytes bytes, MIME\n"; |
| 62 | + $ok = false; |
| 63 | + } |
| 64 | +} |
| 65 | +var_dump($ok); |
| 66 | +?> |
| 67 | +--EXPECT-- |
| 68 | +clean 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 69 | +leading and trailing whitespace 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 70 | +space inside a group 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 71 | +space between groups 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 72 | +a space after every character 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 73 | +MIME lines 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 74 | +PEM lines 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 75 | +short lines 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 76 | +line break before the padding 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 77 | +line break inside the padding 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 78 | +line break after the padding 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 79 | +no padding 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 80 | +no padding, trailing whitespace 'The quick brown fox jumps over the lazy dog, 0123456789.' | 'The quick brown fox jumps over the lazy dog, 0123456789.' |
| 81 | +data after the padding bytes 54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672c20303132333435363738392e105090 | false |
| 82 | +padding in the middle 'The quick brown fox jumps over the lazy dog, 0123456789.' | false |
| 83 | +invalid byte inside a group 'The quick brown fox jumps over the lazy dog, 0123456789.' | false |
| 84 | +invalid byte between groups 'The quick brown fox jumps over the lazy dog, 0123456789.' | false |
| 85 | +high byte 'The quick brown fox jumps over the lazy dog, 0123456789.' | false |
| 86 | +one character '' | false |
| 87 | +two characters 'A' | 'A' |
| 88 | +three characters 'AB' | 'AB' |
| 89 | +five characters 'ABC' | false |
| 90 | +only whitespace '' | '' |
| 91 | +only padding '' | false |
| 92 | +empty '' | '' |
| 93 | +bool(true) |
0 commit comments