From f28afa8ccc59bfc9cc84950a0ea7ec818cb98da1 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 23 Jul 2026 14:37:07 -0400 Subject: [PATCH] Fix convert.quoted-printable-decode of lowercase hex digits The stream filter's nibble decoder accepts lowercase a-f via isxdigit() but decodes them as (*ps - 0x37), correct only for uppercase A-F. Bytes whose hex spelling uses a lowercase digit are silently corrupted (=cd decodes to 0xed, =0a to 0x2a). Decode lowercase with (*ps - 0x57). --- ext/standard/filters.c | 2 +- .../tests/filters/qp_decode_lowercase.phpt | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/filters/qp_decode_lowercase.phpt diff --git a/ext/standard/filters.c b/ext/standard/filters.c index 0c08600648cd..89e5b5f9e6eb 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -953,7 +953,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins err = PHP_CONV_ERR_INVALID_SEQ; goto out; } - next_char = (next_char << 4) | (*ps >= 'A' ? *ps - 0x37 : *ps - 0x30); + next_char = (next_char << 4) | (*ps >= 'a' ? *ps - 0x57 : (*ps >= 'A' ? *ps - 0x37 : *ps - 0x30)); scan_stat++; ps++, icnt--; if (scan_stat != 3) { diff --git a/ext/standard/tests/filters/qp_decode_lowercase.phpt b/ext/standard/tests/filters/qp_decode_lowercase.phpt new file mode 100644 index 000000000000..50a6c454d370 --- /dev/null +++ b/ext/standard/tests/filters/qp_decode_lowercase.phpt @@ -0,0 +1,20 @@ +--TEST-- +convert.quoted-printable-decode: lowercase hex digits decode correctly +--FILE-- + ', bin2hex(stream_get_contents($fp)), "\n"; + fclose($fp); +} +?> +--EXPECT-- +=cd => cd +=0a => 0a +=da => da +=CD => cd +=AB => ab +=ab => ab