<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/82748>82748</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Assertion error when loading AST of the same file twice under different directories.
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
thebesttv
</td>
</tr>
</table>
<pre>
The assertion `((!RequiresNullTerminator || BufEnd[0] == 0) && "Buffer is not null terminated!")` fails (stacktrace `#5`) when building AST from files provided by compile_commands using `Tool.buildASTs(ASTs)`. Code in `main.cpp` at bottom.
Files to reproduce: [segFault.zip](https://github.com/llvm/llvm-project/files/14383351/segFault.zip)
The `compile_commands.json` provided as argument:
``` json
[
{
"command": "cc -c -I. ../poison.c",
"directory": "/home/thebesttv/vul/llvm-project/segFault/build",
"file": "/home/thebesttv/vul/llvm-project/segFault/poison.c"
},
{
"command": "cc -c -I. ../poison.c",
"directory": "/home/thebesttv/vul/llvm-project/segFault/build-static",
"file": "/home/thebesttv/vul/llvm-project/segFault/poison.c"
}
]
```
`segFault` directory structure:
```
.
├── build
│ └── config-poison.h
├── build-static
│ └── config-poison.h
├── compile_commands.json
└── poison.c
```
Here the file `poison.c` is compiled twice, once under `build/`, another under `build-static/`.
Both directories have `config-poison.h`, included by `poison.c`.
Clang version: 675791335285fa86434dc46e5c92f543e0e79d19
Stacktrace:
```
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: ./build-debug/bin/demo-main segFault/compile_commands.json
1. ../poison.h:1:2: current parser token 'include'
#0 0x00005605aaace184 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/thebesttv/vul/llvm-project/llvm/lib/Support/Unix/Signals.inc:723:22
#1 0x00005605aaace597 PrintStackTraceSignalHandler(void*) /home/thebesttv/vul/llvm-project/llvm/lib/Support/Unix/Signals.inc:798:1
#2 0x00005605aaacb9cf llvm::sys::RunSignalHandlers() /home/thebesttv/vul/llvm-project/llvm/lib/Support/Signals.cpp:105:20
#3 0x00005605aaacda6b SignalHandler(int) /home/thebesttv/vul/llvm-project/llvm/lib/Support/Unix/Signals.inc:413:1
#4 0x00007fe07468b770 (/usr/lib/libc.so.6+0x3c770)
#5 0x00005605aab11a0e llvm::MemoryBuffer::init(char const*, char const*, bool) /home/thebesttv/vul/llvm-project/llvm/lib/Support/MemoryBuffer.cpp:53:3
#6 0x00005605aab140b6 (anonymous namespace)::MemoryBufferMMapFile<llvm::MemoryBuffer>::MemoryBufferMMapFile(bool, int, unsigned long, unsigned long, std::error_code&) /home/thebesttv/vul/llvm-project/llvm/lib/Support/MemoryBuffer.cpp:224:3
#7 0x00005605aab137ae llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>> getOpenFileImpl<llvm::MemoryBuffer>(int, llvm::Twine const&, unsigned long, unsigned long, long, bool, bool, std::optional<llvm::Align>) /home/thebesttv/vul/llvm-project/llvm/lib/Support/MemoryBuffer.cpp:484:25
#8 0x00005605aab12cc7 llvm::MemoryBuffer::getOpenFile(int, llvm::Twine const&, unsigned long, bool, bool, std::optional<llvm::Align>) /home/thebesttv/vul/llvm-project/llvm/lib/Support/MemoryBuffer.cpp:529:49
#9 0x00005605aaa60cb9 (anonymous namespace)::RealFile::getBuffer(llvm::Twine const&, long, bool, bool) /home/thebesttv/vul/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp:231:46
#10 0x00005605aaa60219 llvm::vfs::FileSystem::getBufferForFile(llvm::Twine const&, long, bool, bool) /home/thebesttv/vul/llvm-project/llvm/lib/Support/VirtualFileSystem.cpp:126:1
#11 0x00005605ab44d4a0 clang::FileManager::getBufferForFileImpl(llvm::StringRef, long, bool, bool) const /home/thebesttv/vul/llvm-project/clang/lib/Basic/FileManager.cpp:553:43
#12 0x00005605ab44d3a1 clang::FileManager::getBufferForFile(clang::FileEntryRef, bool, bool) /home/thebesttv/vul/llvm-project/clang/lib/Basic/FileManager.cpp:544:53
#13 0x00005605ab48f150 clang::SrcMgr::ContentCache::getBufferOrNone(clang::DiagnosticsEngine&, clang::FileManager&, clang::SourceLocation) const /home/thebesttv/vul/llvm-project/clang/lib/Basic/SourceManager.cpp:124:8
#14 0x00005605ab431a45 clang::SourceManager::getBufferOrNone(clang::FileID, clang::SourceLocation) const /home/thebesttv/vul/llvm-project/clang/include/clang/Basic/SourceManager.h:1050:38
#15 0x00005605ad802245 clang::Preprocessor::EnterSourceFile(clang::FileID, clang::detail::SearchDirIteratorImpl<true>, clang::SourceLocation, bool) /home/thebesttv/vul/llvm-project/clang/lib/Lex/PPLexerChange.cpp:81:8
#16 0x00005605ad7f5933 clang::Preprocessor::HandleHeaderIncludeOrImport(clang::SourceLocation, clang::Token&, clang::Token&, clang::SourceLocation, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*) /home/thebesttv/vul/llvm-project/clang/lib/Lex/PPDirectives.cpp:2568:3
#17 0x00005605ad7f2cd2 clang::Preprocessor::HandleIncludeDirective(clang::SourceLocation, clang::Token&, clang::detail::SearchDirIteratorImpl<true>, clang::FileEntry const*) /home/thebesttv/vul/llvm-project/clang/lib/Lex/PPDirectives.cpp:1989:44
#18 0x00005605ad7eff99 clang::Preprocessor::HandleDirective(clang::Token&) /home/thebesttv/vul/llvm-project/clang/lib/Lex/PPDirectives.cpp:1240:68
#19 0x00005605ad7a90c5 clang::Lexer::LexTokenInternal(clang::Token&, bool) /home/thebesttv/vul/llvm-project/clang/lib/Lex/Lexer.cpp:4481:7
#20 0x00005605ad7a63b3 clang::Lexer::Lex(clang::Token&) /home/thebesttv/vul/llvm-project/clang/lib/Lex/Lexer.cpp:3695:40
#21 0x00005605abcb50bd clang::Preprocessor::CLK_Lexer(clang::Preprocessor&, clang::Token&) /home/thebesttv/vul/llvm-project/clang/include/clang/Lex/Preprocessor.h:2925:3
#22 0x00005605ad83b0c5 clang::Preprocessor::Lex(clang::Token&) /home/thebesttv/vul/llvm-project/clang/lib/Lex/Preprocessor.cpp:872:10
#23 0x00005605abcb76e6 clang::Parser::ConsumeToken() /home/thebesttv/vul/llvm-project/clang/include/clang/Parse/Parser.h:519:12
#24 0x00005605abcab28a clang::Parser::Initialize() /home/thebesttv/vul/llvm-project/clang/lib/Parse/Parser.cpp:582:1
#25 0x00005605abca6e27 clang::ParseAST(clang::Sema&, bool, bool) /home/thebesttv/vul/llvm-project/clang/lib/Parse/ParseAST.cpp:157:28
#26 0x00005605ab6b7d8a clang::ASTFrontendAction::ExecuteAction() /home/thebesttv/vul/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1183:11
#27 0x00005605ab6b7678 clang::FrontendAction::Execute() /home/thebesttv/vul/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1073:38
#28 0x00005605ab58bf91 clang::ASTUnit::Parse(std::shared_ptr<clang::PCHContainerOperations>, std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer>>, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) /home/thebesttv/vul/llvm-project/clang/lib/Frontend/ASTUnit.cpp:1245:39
#29 0x00005605ab58ec12 clang::ASTUnit::LoadFromCompilerInvocation(std::shared_ptr<clang::PCHContainerOperations>, unsigned int, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) /home/thebesttv/vul/llvm-project/clang/lib/Frontend/ASTUnit.cpp:1705:15
#30 0x00005605ab58ef89 clang::ASTUnit::LoadFromCompilerInvocation(std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>, llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>, clang::FileManager*, bool, clang::CaptureDiagsKind, unsigned int, clang::TranslationUnitKind, bool, bool, bool) /home/thebesttv/vul/llvm-project/clang/lib/Frontend/ASTUnit.cpp:1738:38
#31 0x00005605aba7f16a (anonymous namespace)::ASTBuilderAction::runInvocation(std::shared_ptr<clang::CompilerInvocation>, clang::FileManager*, std::shared_ptr<clang::PCHContainerOperations>, clang::DiagnosticConsumer*) /home/thebesttv/vul/llvm-project/clang/lib/Tooling/Tooling.cpp:658:14
#32 0x00005605aba7d68f clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, std::shared_ptr<clang::CompilerInvocation>, std::shared_ptr<clang::PCHContainerOperations>) /home/thebesttv/vul/llvm-project/clang/lib/Tooling/Tooling.cpp:440:31
#33 0x00005605aba7d48e clang::tooling::ToolInvocation::run() /home/thebesttv/vul/llvm-project/clang/lib/Tooling/Tooling.cpp:425:23
#34 0x00005605aba7ee1e clang::tooling::ClangTool::run(clang::tooling::ToolAction*) /home/thebesttv/vul/llvm-project/clang/lib/Tooling/Tooling.cpp:623:11
#35 0x00005605aba7f294 clang::tooling::ClangTool::buildASTs(std::vector<std::unique_ptr<clang::ASTUnit, std::default_delete<clang::ASTUnit>>, std::allocator<std::unique_ptr<clang::ASTUnit, std::default_delete<clang::ASTUnit>>>>&) /home/thebesttv/vul/llvm-project/clang/lib/Tooling/Tooling.cpp:671:13
#36 0x00005605aa92e572 main /home/thebesttv/vul/llvm-project/clang/tools/demo/main.cpp:40:12
#37 0x00007fe074674cd0 (/usr/lib/libc.so.6+0x25cd0)
#38 0x00007fe074674d8a __libc_start_main (/usr/lib/libc.so.6+0x25d8a)
#39 0x00005605aa92e0c5 _start (/home/thebesttv/vul/llvm-project/build-debug/bin/demo-main+0x49f0c5)
Bus error (core dumped)
```
It seems that shortening the content of `build/config-poison.h` will not cause the assertion to fail; changing the order of the two entries in `compile_commands.json` will not, either.
After some digging, it seems the problem is caused by `SeenFileEntries` in [FileManager.cpp](https://github.com/llvm/llvm-project/blob/675791335285fa86434dc46e5c92f543e0e79d19/clang/lib/Basic/FileManager.cpp#L209), which records file by name. It seems the same file manager is used throughout the program, so the second time `./config-poison.h` gets processed, `build/config-poison.h` is used, not `build-static/config-poison.h`.
Commenting out [these if checks](https://github.com/llvm/llvm-project/blob/675791335285fa86434dc46e5c92f543e0e79d19/clang/lib/Basic/FileManager.cpp#L210-L215) seems to bypass the problem.
I encountered this problem when trying to read function declarations in QEMU, and reduced the test cases down to 3 files.
I'm quite new to Clang, and I wonder: is `Tool.buildASTs(ASTs)` (and `FrontendAction`) not meant to be used like this, or is this a bug?
Thans a lot!
<details>
<summary>Code that loads AST from compile_commands.json: <code>main.cpp</code></summary>
``` cpp
#include "clang/AST/ASTContext.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PrettyStackTrace.h"
#include <filesystem>
using namespace clang;
using namespace clang::tooling;
using namespace llvm;
namespace fs = std::filesystem;
std::unique_ptr<CompilationDatabase>
getCompilationDatabase(fs::path buildPath) {
llvm::errs() << "Getting compilation database from: " << buildPath << "\n";
std::string errorMsg;
std::unique_ptr<CompilationDatabase> cb =
CompilationDatabase::autoDetectFromDirectory(buildPath.string(),
errorMsg);
if (!cb) {
llvm::errs() << "Error while trying to load a compilation database:\n"
<< errorMsg << "Running without flags.\n";
exit(1);
}
return cb;
}
int main(int argc, const char **argv) {
llvm::InitLLVM X(argc, argv);
fs::path compile_commands = fs::canonical(fs::absolute(argv[1])).string();
std::unique_ptr<CompilationDatabase> cb =
getCompilationDatabase(compile_commands);
ClangTool Tool(*cb, cb->getAllFiles());
std::vector<std::unique_ptr<ASTUnit>> ASTs;
Tool.buildASTs(ASTs);
return 0;
}
```
</details>
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMW0tz2zqy_jXwBhUVCb4XXsiydY9rnElu7Jm6OxcItiTMIQEdALTj-fW3AL6pR5zYPpVUypJIPL7-utFoAA2qNd8KgEsUXaHo-oLWZifVpdlBDtqYp4tcFi-XDzvAVGtQhkuBUewhkrr__jf4q-YK9D_rsnwAVXFBjVQYJSuUrPBVvbkRBYquPBRdYxRco-Aae4hkGJEYkRgjQq7qzQYU5hoLabCoyxKbtiEoEPERIYhkKPYw3lBeaoxIqg1lfxpFGTRggsh9ZPh5BwLnNS8LLrZ4ef-AN0pWeMNL0Hiv5BMvoMD5C2ay2vMSHpmsKioKjWtta6DYe5CyXLgmlvcPGpG0-bAIFnglC8DcUVBRLhZsv7fIqMG5NEZWC-RdI2_Z_F27Xo3ECvZKFjUDFCwxiq40bNe0Ls3iv3yPomtE0p0xe42CJSJrRNZbbnZ1vmCyQmRdlk_dx6e9kv8BZhBZO4kQWfthkAZB5COynrRKsjESqz8Ue3OhF__RUlj8PTNUY6q2dQXCWDRNE7HX_MeuePMsumq-YIwxSkY_3ANC2i6s8qzMhDCGPzH86XaBFwtE1nvJtRQL5rS7OqhecAXMSPUyNIDIeicrQGTdGyci66e6PCSnYwKRtVPkiU4sh29tfyzHiJDrSX-_PUGftKGGn-rrQ3lqzel6Zmv9z76N2MO90FgbVTNTKzi00uZnNxBvCMpClK3aL6nXf2ncxKRYStCKoKXX_MVd5fBIZSbFhm8_tWLtXtlbx_Pf1enxAT-pdqyfXlnHmP0DFGCzA-dUrVfpS8ee9eJtnwU2z5wBIissBQNciwKULd6OyLXz2CtMhTQ7ULP3vUHaYq0ur6TZ9SbAQeMdfWrd2pSWpmEuWFm33n6KcuKkVyUVW_wESnMprInHSZRkfhBEJI02NI3DICxYGEPEMrKJwgA8SLLCn_jX-34-OmWPX-9ulvc3WNd5xQ2mOK-3dlqQytgJ4qfdP9e6dv4fU1F0ojqtMEX1DucdnsUIIC7qat8D9BbNAP-q5FbRqvf7Fgde9J6hgLze2l9cILIuoJKf7MyHR2P7jJX5bSdjl7ZDwdJHwdI5FFYrBcLgPVUaFDbyTxAYkaQVCZGkdReIBB72vnue50WxF1FKGfhpiB0_wRIFS_2imy9fFRfGSfzgVELSoZCiz49SGwW0ciGItRPTBCSvdmudSniOyPq-3lstIrL-l-Df7QO-FbTUCy4YCpYJCayoZJDCn0sRZQmeQW7a-IOKogSFSPokeYHI8iNxZqlTSw-TzGDmGdscI_tbLSZotYsL3wNnB9DGWMHS9yJLpDcgDGYICxrneM7cx2o39IMpa2GLKdmAl4RxmieJhx0j61qrvtmS52yh5SJG5Mr7HrAk8fqIzTYTTUTLfZ96MCL_M1RSvTSBc_OEC24QSdmOKjtLaOOsZYUPHuRSlu9DyBhEq6PIshEMYsQzMUIvtyF_SoUUL5WsNRa0Ar13gzQ7lO3zZ7q3QTQKVqeEvzlTi6SNtO0YX-FauMVOgUsptkcfaFM0DYJSUj0yaV1Q_GGEERJOGUtmjAUJHSv-xqL6olCw6oHWgv9Vw-PeqNMsjQUrYGPd9mMBJZgfMGv_4y2YL3sQltHbal-erdGOt9UI8sMzF9CZYPw6LXSfnfq6z14IubcLUToFsyz5VjgUH6StMLXaItGgrnSmLsJYcnacjsj8RbJ-M04iN27Dke_Kpm459lie_WjQfwNaNgO9Jakz3PQcN8cpeQ9B_82VqRtI9y_aQNWN18AGLmHchngk8L25tMTPRgp92rTT5NDUTMa1VK01_F6i-iQepjYr6SRuycOwCKmHmY2eBwk_U0G3I1ufiOi8x1jMe6O42H6DzTkJHQs_I2cDqRP0imq3jBih6yzXzVZhMEhI5hIG1P8pCe0MPC1-I4x6aSV8g-5eLVMYNtNwL1MwlSnd-NFEa_eKfd624qykMCDMirLdfCR-Uf-UYibfNadbIbXhTN-ILRfQ2uoJxg5e3staMbiTjFrH9Y66bhqeMuO7mTYdiAmnxAQ-DaNDdMfVfYwNZ-HXHydivyDqnxwXd9fEyp6NK0biTiLKIvUImYr71e1RMtBattLeCAOqafu4bR9IW4ChvGwlB6rY7pqrWwOKGqna2MGoGtx8dJandxgkd2DD9a9f7-A7qNWOii20ppD6U0uYRKlFsomyIDhPTbO8-ANoAeq20csXK6DzqOlZuUYvH-xa93BYnHh8tqlfZ753UqNVwjuwfu22afgTdMs3EsXpEOpa2pMZ7YQV5DW0t4T3Pbyd8d-fPT9LXZgVDvSlU_pgs8my19B3greBmg_BT0LrkOLRqMum-GnmsYlDcuO2_-rg3VqPZCPcE8jfzWu4vrugP3T-IumRE2-GPA7y4DTyD6N5DDKIs8hi9QaU03CN5ZGXF-ftY3X3j8cG-wTypOAZb_VLAh3Oaq0NjTp1UxrJSDTxH4RMZ7QgnxnQoYAfqY0J4HaeSYibiwfIwUwnSQzxBLLbBO2DMV1X0EL82S210_y6PrrPhtvIz9wYHYBOgyNGc5LSU0BvBTeclvy_8OswGyZn0NqQNiWTdQiJZthiIMkBtuX9w2xegIpOnMQ7OIsJ3uX9Q-fsosQa7ODryCTCyOM8KaZ0Lu8f1soF38WSmeYcwkZg34HVBtpHbyS362D0tWm4Q-2nbi9zxHQyhx0n6WT2O435w9F6STCNcMlkQsyjNN9k_ozkfwluRkbiEgna3RO9owqKdhttbE2rP-yyiHIB6svehgRcCt1GAn_TJtxki-hWGFVr_gTfYLMS5uusy6MbDj-7_XNSFy2Hw6zufHI2KCGbKQGYT04q4U7SYq1ktWrOj9SteOrjtjdqpt82O9hi-534S9yZhh_1_E2PuCx_mzT7IP6O1JpZ9S8x_wOmz-4fHI2v-_2D5dh5jwWhe1MrsM3pf3DL86H-x5O-okKXDrOlsqsx31d98-xwRu1BOvVd0zPBnCYbP6Y_2jNd3j9c1bwsQI39r6rFO5nBWTW8zUaOGkEb8Ki3LqIepCy5-91-a2mPI3fCOSyhpkecOU2KON2MsZm2pTZWlOWYo2NkHx6_jRaZij8NsZ3lvK31Oj4_ZLR-AMuhW-gFQxQxPaa1LIcp_CzLbw0nTqJ1iwoyrCqCcIYWwD-N1uWO2BbHQM-J1oVyH2ThZBbBTc-RrV8hWfhaacYpkL2RPbnkm5Pnj0dmqrNhz7GZ7WZu2LQsrT38Hd22nb9tQXhSPYlv1TMytun5eEYgSgh22TW_0LnVpW5TdBBZ9-mpbltgsrzrT5nbLIUkZMWPsxRIxIohS8E2k86bscuax0db7VEbqsxjK8uPGi5SOmk4m_Nil_ZNk21rryXnbA6T6z3MNh6L-u6vao3d2b_tiEkFLmkKigHfLEPR_b01WANUGpsdNVjvpDIguNg2GVnNsQqWm3H622HSGn7mZemSoBmtdZPNNSRdG-nSn1FwhdmO2nipaV2qApRt2_4wzxKDMC47rslSPpny23VmRwpwswM1SYtbbgworGUFuODbLW8O5_ggJ-C9knkJlcv5s4C7TLt7aA64bxogLi1QYBRdzc-rfi3zOS-ltaFXp-m99vSMBHfEy6yeyQo_7zjbYQVMqkI3mY75iwvCFvh2TIKmVZsJWTVtWTocGWanZL3dydp0bG0VrZxjkk1VYFIU2PDKZTEujhvFFozLXGegNbhI9bwRtd3bgtaUDhMqD-tM8yFlVYEw1rwsdBRdmR1owHyD2Q7Yn_o3VJvvfbojvh3EnWYkzl_2VE8MdSLmLQbBZC0MKKcrrnt7dncIjHpxI0xiBbTAm1q4qRsXwEraxlDWrP_35vO_mjTWAisoauZaA2xA23GsQeNCPrvhGzTXEFoYt4gkFf6r5gawgGdbYNUI3DR2i5-lKFzEaHV6_mJCs1YobKnZpkxzLcJaQgVUuGTTHBoDLfmf4CR3ObrOcB0PLjkVBevpBQIq7JvSOgx__AYFq-b8xIWUbWq3nanrqqLqBQU37s6Ec4ylpIUebmUc903B0lZ3mVfBzTCLrZzpuofNj6GDMRyMh-sKtl73kARdkiwipLMst0to_7qT7-9msRulpx-vMkzuoyD-mhqaUw0_Vb8LDk7XaQfSkKtxK7i5u_v355-p81WBMS9Daum07pE2gpUz037rY1a0uSfTL0e7aPLqB-8n0ebJws3mQf96eLHRGAXXQ0g3hng1h3g8SDyir5F4WzDHCpC02w_aU7Nrkvi_UrNzAeL0Vsew8QFqyIINVihYWcX8DxjnVNnQCy7abtxwaK9XdFX6rkZtoGgl3EWMScfDCtDl0zThy2e9PVXsFaxglrvbWpObIBgfLexC9NrIazDAzFrJ6nq4m5L2YiwadA0vB7dMfvJfLyLJZlLyTRMh-iw_oqNX6MmlWNr5v4TRJGA9F6ZHlWfbavVyTqS2hw75qMdvtXCx4jM3LlrYlHSrF8d17YT_7nJ9_UPh-_s0zU8FplYCs3w8RoYi3ScXBjfhcGq_UrVlbu_CZaq4LQ23YF1StX06a_ede8L_Z6ejtpm21pFhav9NRtfBnTw75LsSjAopOHOnv90zmmtZNqcNrpvoynfRiY3ipvb27kPhpL-YC3Fa9n69jd2i2wJdWqtdYZZ_QsHNFsyydIl5uhs1JwX5wbp8ssrFLm6YNnQytjgOvbUs74RhHVsiNZP2ECpcFJdBkQUZvYBLP_HSOCVRSC52l-FmE6VJnGVpTPMsYFFEGWMxiwKSAmFwwS-JR0KPkMD3PELIImJxFqUkT1hCaJBSFHpQUV4urGkupNpeuOsylylJwvSipDmU2t13JcRGXu6l867XF-rSha15vdUo9EqujR5aMdyUcLnsl2TQugoQzj90N07btdiwMnAXodoLTgXfbMDdeBndZFpc1Kq8_PVLQE6w_w8AAP__pW1RVA">