diff --git a/program/lib/Roundcube/rcube_vcard.php b/program/lib/Roundcube/rcube_vcard.php index 4d37e7dd01..f34fa75cfe 100644 --- a/program/lib/Roundcube/rcube_vcard.php +++ b/program/lib/Roundcube/rcube_vcard.php @@ -755,7 +755,7 @@ private static function vcard_decode($vcard) $value = strtoupper($value); // add next line(s) to value string if QP line end detected if ($value == 'QUOTED-PRINTABLE') { - while (preg_match('/=$/', $lines[$i])) { + while (isset($lines[$i]) && preg_match('/=$/', $lines[$i]) && isset($lines[$i + 1])) { $data .= "\n" . $lines[++$i]; } } @@ -1049,7 +1049,7 @@ private static function detect_encoding($string) $enc = $matches ? strtoupper($matches[1]) : 'BASE64'; // add next line(s) to value string if QP line end detected if ($enc == 'QUOTED-PRINTABLE') { - while (preg_match('/=$/', $lines[$i])) { + while (isset($lines[$i]) && preg_match('/=$/', $lines[$i]) && isset($lines[$i + 1])) { $data .= "\n" . $lines[++$i]; } } diff --git a/tests/Framework/VCardTest.php b/tests/Framework/VCardTest.php index acd5ea38f7..61ecaca2ea 100644 --- a/tests/Framework/VCardTest.php +++ b/tests/Framework/VCardTest.php @@ -102,6 +102,36 @@ public function test_parse_six() $this->assertCount(1, $result['address:work'], 'ITEM1.-prefixed entry'); } + /** + * A QUOTED-PRINTABLE soft-line-break ('=') on the very last line must not + * cause reading past the end of the internal lines array. + */ + public function test_parse_qp_soft_break_on_last_line() + { + $errors = []; + set_error_handler(static function ($errno, $errstr) use (&$errors) { + $errors[] = $errstr; + + return true; + }); + + try { + // Last line ends with '=' (QP soft line break) with no following line + $vcard_string = "BEGIN:VCARD\r\n" + . "VERSION:3.0\r\n" + . "FN:Test\r\n" + . 'NOTE;ENCODING=QUOTED-PRINTABLE:Hello='; + + $vcard = new \rcube_vcard($vcard_string, null, true); + $result = $vcard->get_assoc(); + } finally { + restore_error_handler(); + } + + $this->assertSame([], $errors, 'No PHP warnings/errors while decoding'); + $this->assertSame('Hello', $result['notes'][0], 'Best-effort QP decode of the dangling line'); + } + /** * Extra whitespace at start of continuation line (#9593/1). */