VYPR
Moderate severityNVD Advisory· Published Mar 6, 2026· Updated Mar 6, 2026

pypdf: Inefficient decoding of ASCIIHexDecode streams

CVE-2026-28804

Description

pypdf is a free and open-source pure-python PDF library. Prior to version 6.7.5, an attacker who uses this vulnerability can craft a PDF which leads to long runtimes. This requires accessing a stream which uses the /ASCIIHexDecode filter. This issue has been patched in version 6.7.5.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
pypdfPyPI
< 6.7.56.7.5

Affected products

1

Patches

1
648c627d2657

SEC: Improve the performance of the ASCIIHexDecode filter (#3666)

https://github.com/py-pdf/pypdfStefanMar 2, 2026via ghsa
2 files changed · +27 28
  • pypdf/filters.py+21 28 modified
    @@ -35,6 +35,7 @@
     __author__ = "Mathieu Fenniak"
     __author_email__ = "biziqe@mathieu.fenniak.net"
     
    +import binascii
     import math
     import os
     import shutil
    @@ -343,34 +344,26 @@ def decode(
             """
             if isinstance(data, str):
                 data = data.encode()
    -        retval = b""
    -        hex_pair = b""
    -        index = 0
    -        while True:
    -            if index >= len(data):
    -                logger_warning(
    -                    "missing EOD in ASCIIHexDecode, check if output is OK", __name__
    -                )
    -                break  # Reached end of string without an EOD
    -            char = data[index : index + 1]
    -            if char == b">":
    -                break
    -            if char.isspace():
    -                index += 1
    -                continue
    -            hex_pair += char
    -            if len(hex_pair) == 2:
    -                retval += bytes((int(hex_pair, base=16),))
    -                hex_pair = b""
    -            index += 1
    -        # If the filter encounters the EOD marker after reading
    -        # an odd number of hexadecimal digits,
    -        # it shall behave as if a 0 (zero) followed the last digit.
    -        # For every even number of hexadecimal digits, hex_pair is reset to b"".
    -        if hex_pair != b"":
    -            hex_pair += b"0"
    -            retval += bytes((int(hex_pair, base=16),))
    -        return retval
    +
    +        # Stop at EOD
    +        eod = data.find(b">")
    +        if eod == -1:
    +            logger_warning(
    +                "missing EOD in ASCIIHexDecode, check if output is OK",
    +                __name__,
    +            )
    +            hex_data = data
    +        else:
    +            hex_data = data[:eod]
    +
    +        # Remove whitespace
    +        hex_data = b"".join(hex_data.split())
    +
    +        # Pad if odd length
    +        if len(hex_data) % 2 == 1:
    +            hex_data += b"0"
    +
    +        return binascii.unhexlify(hex_data)
     
     
     class RunLengthDecode:
    
  • tests/test_filters.py+6 0 modified
    @@ -1043,3 +1043,9 @@ def test_runlengthdecode__decode_limit():
         # Use a very low limit for this exact comparison, otherwise *pytest* takes ages to render a failure diff.
         with mock.patch("pypdf.filters.RUN_LENGTH_MAX_OUTPUT_LENGTH", uncompressed_size):
             assert RunLengthDecode.decode(encoded) == b"A" * uncompressed_size
    +
    +
    +@pytest.mark.timeout(10)
    +def test_asciihexdecode__speed():
    +    encoded = (b"41" * 1_200_000) + b">"
    +    ASCIIHexDecode.decode(encoded)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.