During extraction of the attached 7zip archive via
/p7zip_16.02/bin/7za e -so -y /testcase
an out-of-bounds read and segmentation fault (SIGSEGV) is triggered. This possibly opens up other attack vectors to an attacker if files from untrusted sources are processed.
For reproduction of the crash, I attach a Docker image. Run ./build_upstream.sh to build the docker image and ./reproduce-upstream.sh to reproduce the crash.
If you need further details, please do not hesitate to ask.
Version
The input was tested on p7zip_16.02
Valgrind
[+] Running /p7zip_16.02/bin/7za e -so -y /testcase
==1== Memcheck, a memory error detector
==1== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==1== Command: /p7zip_16.02/bin/7za e -so -y /testcase
==1==
ERRORS:
Headers Error
mmmERROR: Data Error : testcase~
ERROR: Data Error : testcase~
ERROR: Data Error : testcase~
ERROR: Unsupported Method : testcase~
==1== Invalid read of size 8
==1== at 0x1601B1: NCoderMixer2::CMixerMT::GetCoder(unsigned int) (CoderMixer2.cpp:869)
==1== by 0x13D4FB: NArchive::N7z::CDecoder::Decode(IInStream*, unsigned long long, NArchive::N7z::CFolders const&, unsigned int, unsigned long long const*, ISequentialOutStream*, ICompressProgressInfo*, ISequentialInStream**, ICryptoGetTextPassword*, bool&, bool&, UString&, bool, unsigned int) (7zDecode.cpp:357)
==1== by 0x1426B1: NArchive::N7z::CHandler::Extract(unsigned int const*, unsigned int, int, IArchiveExtractCallback*) (7zExtract.cpp:351)
==1== by 0x1C9E78: DecompressArchive (Extract.cpp:208)
==1== by 0x1C9E78: Extract(CCodecs*, CObjectVector<COpenType> const&, CRecordVector<int> const&, CObjectVector<UString>&, CObjectVector<UString>&, NWildcard::CCensorNode const&, CExtractOptions const&, IOpenCallbackUI*, IExtractCallbackUI*, IHashCalc*, UString&, CDecompressStat&) (Extract.cpp:445)
==1== by 0x1EDF43: Main2(int, char**) (Main.cpp:923)
==1== by 0x1F141A: main (MainAr.cpp:66)
==1== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1==
==1==
==1== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==1== Access not within mapped region at address 0x0
==1== at 0x1601B1: NCoderMixer2::CMixerMT::GetCoder(unsigned int) (CoderMixer2.cpp:869)
==1== by 0x13D4FB: NArchive::N7z::CDecoder::Decode(IInStream*, unsigned long long, NArchive::N7z::CFolders const&, unsigned int, unsigned long long const*, ISequentialOutStream*, ICompressProgressInfo*, ISequentialInStream**, ICryptoGetTextPassword*, bool&, bool&, UString&, bool, unsigned int) (7zDecode.cpp:357)
==1== by 0x1426B1: NArchive::N7z::CHandler::Extract(unsigned int const*, unsigned int, int, IArchiveExtractCallback*) (7zExtract.cpp:351)
==1== by 0x1C9E78: DecompressArchive (Extract.cpp:208)
==1== by 0x1C9E78: Extract(CCodecs*, CObjectVector<COpenType> const&, CRecordVector<int> const&, CObjectVector<UString>&, CObjectVector<UString>&, NWildcard::CCensorNode const&, CExtractOptions const&, IOpenCallbackUI*, IExtractCallbackUI*, IHashCalc*, UString&, CDecompressStat&) (Extract.cpp:445)
==1== by 0x1EDF43: Main2(int, char**) (Main.cpp:923)
==1== by 0x1F141A: main (MainAr.cpp:66)
==1== If you believe this happened as a result of a stack
==1== overflow in your program's main thread (unlikely but
==1== possible), you can try to increase the size of the
==1== main thread stack using the --main-stacksize= flag.
==1== The main thread stack size used in this run was 8388608.
==1==
==1== HEAP SUMMARY:
==1== in use at exit: 4,205,541 bytes in 318 blocks
==1== total heap usage: 1,212 allocs, 894 frees, 5,689,428 bytes allocated
==1==
==1== LEAK SUMMARY:
==1== definitely lost: 0 bytes in 0 blocks
==1== indirectly lost: 0 bytes in 0 blocks
==1== possibly lost: 0 bytes in 0 blocks
==1== still reachable: 4,205,541 bytes in 318 blocks
==1== of which reachable via heuristic:
==1== newarray : 1,296 bytes in 2 blocks
==1== suppressed: 0 bytes in 0 blocks
==1== Rerun with --leak-check=full to see details of leaked memory
==1==
==1== For lists of detected and suppressed errors, rerun with: -s
==1== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
valgrind: the 'impossible' happened:
main(): signal was supposed to be fatal
host stacktrace:
==1== at 0x58046FFA: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==1== by 0x58047127: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==1== by 0x58047390: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==1== by 0x580473C0: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==1== by 0x580BA566: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
==1== by 0x580F6117: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/memcheck-amd64-linux)
sched status:
running_tid=1