提出 #632365: podofo podofoencrypt PoDoFo version 1.1.0-dev (commit 053cf47) compiled on Jul 30 2025 and the newest master version. Heap Use-After-Free情報

タイトルpodofo podofoencrypt PoDoFo version 1.1.0-dev (commit 053cf47) compiled on Jul 30 2025 and the newest master version. Heap Use-After-Free
説明# PoDoFo Deep Recursion Use-After-Free in PDF Dictionary Parsing ## Summary During fuzzing of the PoDoFo PDF library's podofoencrypt tool, a critical heap-use-after-free vulnerability was discovered that occurs specifically during deep recursive parsing of nested PDF dictionary structures. The vulnerability manifests when extremely nested dictionary structures (96+ levels of recursion) cause stack exhaustion leading to heap memory corruption. This vulnerability is distinct from standard dictionary parsing issues as it involves recursive depth limits and stack/heap interaction causing memory management failures in the `PdfTokenizer::ReadDictionary` function. ## Technical Details - **Vulnerability Type**: Heap Use-After-Free (Deep Recursion Induced) - **Affected Component**: PoDoFo PDF Library - PdfTokenizer - **Affected Function**: `PdfTokenizer::ReadDictionary` (recursive calls) - **Source File**: `PdfTokenizer.cpp` - **Line Number**: 464-505 (recursive execution) - **Signal**: SIGABRT (6) - **Memory Access**: READ of size 4 - **Recursion Depth**: 96+ levels - **Stack Frame Pattern**: Repeated `ReadDictionary` → `ReadNextVariant` → `ReadDictionary` ## Vulnerability Mechanism and Root Cause This heap-use-after-free vulnerability is triggered by excessively deep recursion in PDF dictionary parsing, creating a unique failure mode distinct from normal dictionary parsing issues. The root cause involves the interaction between stack exhaustion and heap memory management. The vulnerability sequence involves: 1. **Deep Recursion Initiation**: Malformed PDF contains deeply nested dictionary structures (<<</>>) 2. **Stack Frame Accumulation**: Each dictionary level creates new stack frames via `ReadDictionary` → `tryReadDataType` → `ReadNextVariant` → `ReadDictionary` 3. **Resource Exhaustion**: At approximately 96+ recursion levels, stack space approaches limits 4. **Heap Corruption**: Stack pressure causes heap allocator corruption or premature cleanup 5. **Use-After-Free**: `PdfName::NameData` objects are accessed after being freed due to corrupted memory management state The extended call chain demonstrates the recursion pattern: ``` ReadDictionary() #1 → ReadDictionary() #2 → ... → ReadDictionary() #96+ ``` This recursive depth creates a fundamentally different memory corruption scenario compared to normal dictionary parsing, requiring separate mitigation strategies focused on recursion limits rather than just PdfName lifetime management. ## AddressSanitizer Report ``` WARNING: Invalid number while parsing content ================================================================= ==3576531==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000000498 at pc 0x7f26bed23147 bp 0x7fff2716f780 sp 0x7fff2716f778 READ of size 4 at 0x603000000498 thread T0 #0 0x7f26bed23146 in __gnu_cxx::__exchange_and_add_single(int*, int) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/ext/atomicity.h:84:29 #1 0x7f26bed23146 in __gnu_cxx::__exchange_and_add_dispatch(int*, int) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/ext/atomicity.h:99:14 #2 0x7f26bed23146 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:165:6 #3 0x7f26bed23146 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:705:11 #4 0x7f26bed23146 in std::__shared_ptr<PoDoFo::PdfName::NameData, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/shared_ptr_base.h:1154:31 #5 0x7f26bed23146 in PoDoFo::PdfName::~PdfName() /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfName.cpp:33:16 #6 0x7f26be9cdeac in std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>::~pair() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_iterator.h:2488:12 #7 0x7f26be9cdeac in void __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::destroy<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>(std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/ext/new_allocator.h:168:10 #8 0x7f26be9cdeac in void std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>>::destroy<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>(std::allocator<std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>&, std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/alloc_traits.h:535:8 #9 0x7f26be9cdeac in std::_Rb_tree<PoDoFo::PdfName, std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>, std::_Select1st<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>, PoDoFo::PdfNameInequality, std::allocator<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::_M_destroy_node(std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_tree.h:623:2 #10 0x7f26be9cdeac in std::_Rb_tree<PoDoFo::PdfName, std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>, std::_Select1st<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>, PoDoFo::PdfNameInequality, std::allocator<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::_M_drop_node(std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_tree.h:631:2 #11 0x7f26be9cdeac in std::_Rb_tree<PoDoFo::PdfName, std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>, std::_Select1st<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>, PoDoFo::PdfNameInequality, std::allocator<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::_M_erase(std::_Rb_tree_node<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>*) /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_tree.h:1891:4 #12 0x7f26beec3dc0 in std::_Rb_tree<PoDoFo::PdfName, std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>, std::_Select1st<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>, PoDoFo::PdfNameInequality, std::allocator<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::~_Rb_tree() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_tree.h:984:9 #13 0x7f26beec3dc0 in std::map<PoDoFo::PdfName, PoDoFo::PdfObject, PoDoFo::PdfNameInequality, std::allocator<std::pair<PoDoFo::PdfName const, PoDoFo::PdfObject>>>::~map() /usr/lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/stl_map.h:302:22 #14 0x7f26beec3dc0 in PoDoFo::PdfDictionary::~PdfDictionary() /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfDictionary.h:81:18 #15 0x7f26beec3dc0 in PoDoFo::PdfVariant::~PdfVariant() /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfVariant.cpp:94:13 #16 0x7f26beebc1f9 in PoDoFo::PdfTokenizer::ReadDictionary(PoDoFo::InputStreamDevice&, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:505:1 #17 0x7f26beeba5a6 in PoDoFo::PdfTokenizer::tryReadDataType(PoDoFo::InputStreamDevice&, PoDoFo::PdfTokenizer::PdfLiteralDataType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:416:19 #18 0x7f26beeb8952 in PoDoFo::PdfTokenizer::TryReadNextVariant(PoDoFo::InputStreamDevice&, std::basic_string_view<char, std::char_traits<char>> const&, PoDoFo::PdfTokenType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:251:12 #19 0x7f26beeb8952 in PoDoFo::PdfTokenizer::ReadNextVariant(PoDoFo::InputStreamDevice&, std::basic_string_view<char, std::char_traits<char>> const&, PoDoFo::PdfTokenType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:243:10 #20 0x7f26beebaf55 in PoDoFo::PdfTokenizer::ReadDictionary(PoDoFo::InputStreamDevice&, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:464:15 #21 0x7f26beeba5a6 in PoDoFo::PdfTokenizer::tryReadDataType(PoDoFo::InputStreamDevice&, PoDoFo::PdfTokenizer::PdfLiteralDataType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:416:19 #22 0x7f26beeb8952 in PoDoFo::PdfTokenizer::TryReadNextVariant(PoDoFo::InputStreamDevice&, std::basic_string_view<char, std::char_traits<char>> const&, PoDoFo::PdfTokenType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:251:12 #23 0x7f26beeb8952 in PoDoFo::PdfTokenizer::ReadNextVariant(PoDoFo::InputStreamDevice&, std::basic_string_view<char, std::char_traits<char>> const&, PoDoFo::PdfTokenType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:243:10 #24 0x7f26beebaf55 in PoDoFo::PdfTokenizer::ReadDictionary(PoDoFo::InputStreamDevice&, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:464:15 #25 0x7f26beeba5a6 in PoDoFo::PdfTokenizer::tryReadDataType(PoDoFo::InputStreamDevice&, PoDoFo::PdfTokenizer::PdfLiteralDataType, PoDoFo::PdfVariant&, PoDoFo::PdfStatefulEncrypt const*) /workspace/program/podofo-053cf47-Jul30/src/podofo/main/PdfTokenizer.cpp:416:19 #26 0x7f26beeb8952 in PoDoFo::PdfTokenizer::TryReadNextVariant(PoDoFo::InputStreamDevice&, std::basic_string_view<char, std::char_traits<char>> const&, PoDoFo::PdfTok
ソース⚠️ https://github.com/podofo/podofo/issues/276
ユーザー
 xdcao (UID 88377)
送信2025年08月12日 09:28 (9 月 ago)
モデレーション2025年08月23日 17:43 (11 days later)
ステータス重複
VulDBエントリ321227 [PoDoFo 1.1.0-dev PDF Dictionary Parser PdfTokenizer.cpp DetermineDataType メモリ破損]
ポイント0

Do you want to use VulDB in your project?

Use the official API to access entries easily!