diff --git a/Frameworks/OpenMPT/OpenMPT/build/dist.mk b/Frameworks/OpenMPT/OpenMPT/build/dist.mk index 79714a6dc..c914ddf58 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/dist.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/dist.mk @@ -1,4 +1,4 @@ -MPT_SVNVERSION=14311 -MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.6 -MPT_SVNDATE=2021-03-14T15:27:41.476009Z +MPT_SVNVERSION=14391 +MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.7 +MPT_SVNDATE=2021-03-20T17:06:12.434258Z diff --git a/Frameworks/OpenMPT/OpenMPT/build/make/config-afl.mk b/Frameworks/OpenMPT/OpenMPT/build/make/config-afl.mk index fd073cd26..52cec13bd 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/make/config-afl.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/make/config-afl.mk @@ -1,7 +1,7 @@ -CC = contrib/fuzzing/afl/afl-clang-fast -CXX = contrib/fuzzing/afl/afl-clang-fast++ -LD = contrib/fuzzing/afl/afl-clang-fast++ +CC = contrib/fuzzing/afl/afl-clang-lto +CXX = contrib/fuzzing/afl/afl-clang-lto++ +LD = contrib/fuzzing/afl/afl-clang-lto++ AR = ar ifneq ($(STDCXX),) @@ -15,6 +15,10 @@ CFLAGS_STDC = -std=c99 CXXFLAGS += $(CXXFLAGS_STDCXX) CFLAGS += $(CFLAGS_STDC) +DYNLINK=0 +SHARED_LIB=0 +STATIC_LIB=1 + CPPFLAGS += CXXFLAGS += -fPIC -fno-strict-aliasing CFLAGS += -fPIC -fno-strict-aliasing diff --git a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h index e43987fee..a8517a6dc 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h +++ b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h @@ -1,10 +1,10 @@ #pragma once -#define OPENMPT_VERSION_SVNVERSION "14311" -#define OPENMPT_VERSION_REVISION 14311 +#define OPENMPT_VERSION_SVNVERSION "14391" +#define OPENMPT_VERSION_REVISION 14391 #define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.6" -#define OPENMPT_VERSION_DATE "2021-03-14T15:27:41.476009Z" +#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.7" +#define OPENMPT_VERSION_DATE "2021-03-20T17:06:12.434258Z" #define OPENMPT_VERSION_IS_PACKAGE 1 diff --git a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h index 47c02bb5b..6b3ef3df5 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h +++ b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h @@ -18,6 +18,6 @@ OPENMPT_NAMESPACE_BEGIN #define VER_MAJORMAJOR 1 #define VER_MAJOR 29 #define VER_MINOR 08 -#define VER_MINORMINOR 00 +#define VER_MINORMINOR 03 OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/build.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/build.sh index b6a085ed6..833397efe 100755 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/build.sh +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/build.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash cd "${0%/*}" cd ../.. -AFL_HARDEN=1 CONFIG=afl make clean all EXAMPLES=0 TEST=0 OPENMPT123=0 NO_VORBIS=1 NO_VORBISFILE=1 NO_MPG123=1 +AFL_HARDEN=1 CONFIG=afl make clean all EXAMPLES=0 TEST=0 OPENMPT123=0 NO_VORBIS=1 NO_VORBISFILE=1 NO_MPG123=1 CHECKED_ADDRESS=1 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-main.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-main.sh new file mode 100644 index 000000000..8c0e2ff4c --- /dev/null +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-main.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +cd "${0%/*}" +. ./fuzz-settings.sh + +# Create tmpfs for storing temporary fuzzing data +mkdir $FUZZING_TEMPDIR +sudo mount -t tmpfs -o size=300M none $FUZZING_TEMPDIR +rm -rf $FUZZING_TEMPDIR/bin +mkdir $FUZZING_TEMPDIR/bin +cp -d ../../bin/* $FUZZING_TEMPDIR/bin/ + +#export AFL_PRELOAD=$AFL_DIR/libdislocator.so +LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_DIR/afl-fuzz -p exploit -f $FUZZING_TEMPDIR/infile01 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -M fuzzer01 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile01 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-master.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-master.sh deleted file mode 100755 index 227d9695e..000000000 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-master.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash -cd "${0%/*}" -. ./fuzz-settings.sh - -# Create tmpfs for storing temporary fuzzing data -mkdir $FUZZING_TEMPDIR -sudo mount -t tmpfs -o size=200M none $FUZZING_TEMPDIR -rm -rf $FUZZING_TEMPDIR/bin -mkdir $FUZZING_TEMPDIR/bin -cp -d ../../bin/* $FUZZING_TEMPDIR/bin/ - -LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_BIN -f $FUZZING_TEMPDIR/infile01 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -M fuzzer01 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile01 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary1.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary1.sh new file mode 100644 index 000000000..2d6a867b6 --- /dev/null +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary1.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +cd "${0%/*}" +. ./fuzz-settings.sh + +#export AFL_PRELOAD=$AFL_DIR/libdislocator.so +LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_DIR/afl-fuzz -p coe -f $FUZZING_TEMPDIR/infile02 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -S fuzzer02 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile02 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary2.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary2.sh new file mode 100644 index 000000000..97b28395a --- /dev/null +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-secondary2.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +cd "${0%/*}" +. ./fuzz-settings.sh + +#export AFL_PRELOAD=$AFL_DIR/libdislocator.so +LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_DIR/afl-fuzz -p explore -f $FUZZING_TEMPDIR/infile03 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -S fuzzer03 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile03 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-settings.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-settings.sh index f8717d45e..1b280673e 100755 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-settings.sh +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-settings.sh @@ -15,4 +15,4 @@ FUZZING_FINDINGS_DIR=~/libopenmpt-fuzzing # Fuzzer timeout in ms, + = don't abort on timeout FUZZING_TIMEOUT=5000+ # Path to afl-fuzz binary -AFL_BIN=afl/afl-fuzz \ No newline at end of file +AFL_DIR=afl diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-slave.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-slave.sh deleted file mode 100755 index b57fe359e..000000000 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz-slave.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -cd "${0%/*}" -. ./fuzz-settings.sh - -LD_LIBRARY_PATH=$FUZZING_TEMPDIR/bin $AFL_BIN -f $FUZZING_TEMPDIR/infile02 -x all_formats.dict -t $FUZZING_TIMEOUT $FUZZING_INPUT -o $FUZZING_FINDINGS_DIR -S fuzzer02 $FUZZING_TEMPDIR/bin/fuzz $FUZZING_TEMPDIR/infile02 diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz.c b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz.c index 8fb7ee7aa..653dab6d6 100644 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz.c +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/fuzz.c @@ -20,7 +20,7 @@ #include #include -#define BUFFERSIZE 512 +#define BUFFERSIZE 450 // shouldn't match OpenMPT's internal mix buffer size (512) #define SAMPLERATE 22050 static int16_t buffer[BUFFERSIZE]; @@ -46,6 +46,11 @@ int main( int argc, char * argv[] ) { break; } } + openmpt_module_set_position_seconds( mod, 1.0 ); + openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); + openmpt_module_set_position_order_row( mod, 3, 16 ); + openmpt_module_read_mono( mod, SAMPLERATE, BUFFERSIZE, buffer ); + /* fuzz string-related stuff */ openmpt_free_string ( openmpt_module_get_metadata( mod, "date" ) ); openmpt_free_string ( openmpt_module_get_metadata( mod, "message" ) ); diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/get-afl.sh b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/get-afl.sh index 5cd7ea690..b9973722b 100755 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/get-afl.sh +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/get-afl.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash cd "${0%/*}" -AFL_VERSION="$(wget --quiet -O - "https://api.github.com/repos/AFLplusplus/AFLplusplus/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')" -AFL_FILENAME="$AFL_VERSION.tar.gz" +GET_AFL_VERSION?="$(wget --quiet -O - "https://api.github.com/repos/AFLplusplus/AFLplusplus/releases/latest" | grep -Po '"tag_name": "\K.*?(?=")')" +AFL_FILENAME="$GET_AFL_VERSION.tar.gz" AFL_URL="https://github.com/AFLplusplus/AFLplusplus/archive/$AFL_FILENAME" rm $AFL_FILENAME diff --git a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/readme.md b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/readme.md index f63ef9021..bb19163ec 100644 --- a/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/readme.md +++ b/Frameworks/OpenMPT/OpenMPT/contrib/fuzzing/readme.md @@ -2,45 +2,50 @@ libopenmpt fuzz suite ===================== In this directory, you can find the necessary tools for fuzzing libopenmpt with -the American Fuzzy Lop fuzzer (afl-fuzz). +the American Fuzzy Lop fuzzer (afl++). Contents: * `all_formats.dict`: A dictionary containing magic bytes from all supported module formats to make the life of the fuzzer a bit easier. -* `fuzz-master.sh`: Script to launch the main fuzzing process. If you want to +* `fuzz-main.sh`: Script to launch the main fuzzing process. If you want to use just one fuzzer instance, run this one. -* `fuzz-slave.sh`: Script to launch the secondary fuzzing process. It is - recommended to run at least two fuzzer instances, as the deterministic and - random fuzz mode have been found to complement each other really well. +* `fuzz-secondary[1|2].sh`: Scripts to launch the secondary fuzzing process. It + is recommended to run at least two fuzzer instances, as the deterministic and + random fuzz mode have been found to complement each other really well. The two + scripts are set up to use different exploration strategies * `fuzz-settings.sh`: Set up your preferences and afl settings here before the first run. * `fuzz.c`: A tiny C program that is used by the fuzzer to test libopenmpt. -* `get-afl.sh`: A simple script to obtain the latest version of the fuzzer. +* `get-afl.sh`: A simple script to obtain the latest version of afl++. + You can also make it download from a specific branch or tag, e.g. + `GET_AFL_VERSION=stable ./get-afl.sh` to download the latest stable but + unreleased code. Prerequisites ============= -* afl from http://lcamtuf.coredump.cx/afl/ - the makefile expects this to be - installed in `contrib/fuzzing/afl`, as it is automatically done by the - `get-afl.sh` install script. +* [afl++](https://github.com/AFLplusplus/AFLplusplus) - the makefile expects + this to be installed in `contrib/fuzzing/afl`, as it is automatically done by + the `get-afl.sh` install script. * Clang with LLVM dev headers (llvm-config needs to be installed). afl also works with gcc, but our makefile has been set up to make use of afl's - faster LLVM mode. + faster LLVM-LTO mode. How to use ========== -* Run `get-afl.sh`, or manually extract afl to `contrib/fuzzing/afl`, use `make` - to build afl-fuzz, `cd llvm_mode`, `make` to build afl-clang-fast. - If building with either option fails because `llvm-config` cannot be found, - try prepending `LLVM_CONFIG=/usr/bin/llvm-config-3.8` or similar, and read the - afl manual. +* Run `get-afl.sh`, or manually extract afl to `contrib/fuzzing/afl`, use + `make source-only` to build. If building fails because `llvm-config` cannot be + found, try prepending `LLVM_CONFIG=/usr/bin/llvm-config-12` or similar, and + read the afl manual. * Build libopenmpt with the `build.sh` script in this directory. * Set up `fuzz-settings.sh` to your taste. Most importantly, you will have to specify the input directory for first use. The default setup mounts a tmpfs folder for all temporary files. You may change this behaviour if you do not have root privileges. -* Run `fuzz-master.sh` for the first (deterministic) instance of afl-fuzz. -* For a "slave" instance to run on another core, run `fuzz-slave.sh`. -* If you want to make use of even more cores, make a copy of `fuzz-slave.sh` - and adjust "infile02" / "fuzzer02" to "infile03" / "fuzzer03" (they need to be - unique) \ No newline at end of file +* Run `fuzz-main.sh` for the first (deterministic) instance of afl-fuzz. +* For a "secondary" instance to run on another core, run `fuzz-secondary1.sh` + and/or `fuzz-secondary2.sh`. +* If you want to make use of even more cores, create more copies + `fuzz-secondary2.sh` and adjust "infile03" / "fuzzer03" to + "infile04" / "fuzzer04" and so o (they need to be unique). Try variying the + fuzzing strategey (the -p parameter) to get results more quickly. diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md index 0cdc38114..bfcd21910 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md @@ -5,6 +5,17 @@ Changelog {#changelog} For fully detailed change log, please see the source repository directly. This is just a high-level summary. +### libopenmpt 0.5.7 (2021-03-20) + + * [**Sec**] Possible null-pointer dereference read caused by a sequence of + `openmpt::module::read`, `openmpt::module::set_position_seconds` with a + position past the song end, and another `openmpt::module::read` call. + (r14363) + + * IT: Instrument / sample panning was reset on note-off / fade commands. + * IMF: Set Finetune is now implemented correctly. + * Fixed excessive memory consumption with malformed files in various formats. + ### libopenmpt 0.5.6 (2021-03-14) * AMS: Avoid allocating excessive amount of memory for compressed song message diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/dependencies.md b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/dependencies.md index d6eed5c61..02afadba1 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/dependencies.md +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/dependencies.md @@ -24,7 +24,6 @@ Dependencies used for building: * `std::numeric_limits::digits == 8` (enforced by static_assert) - * `sizeof(char) == 1` (enforced by static_assert) * existence of `std::uintptr_t` (enforced by static_assert) * in C++20 mode, `std::endian::little != std::endian::big` (enforced by static_assert) @@ -33,8 +32,6 @@ Dependencies assumed) * representation of basic source character set is identical in char and `wchar_t` (implicitly assumed) - * libopenmpt also has experimental support for platforms without - `wchar_t` support like DJGPP libopenmpt does not rely on any specific implementation defined or undefined behaviour (if it does, that's a bug in libopenmpt). In @@ -43,23 +40,26 @@ Dependencies * shifting signed values is implementation defined * `signed` integer overflow is undefined * `float` and `double` can be non-IEEE754 + + libopenmpt can optionally support for certain incomplete C++ + implementations: + * platforms without `wchar_t` support (like DJGPP) + * platforms without working `std::random_device` (like Emscripten when + running in `AudioWorkletProcessor` context) + * platforms without working `std::high_resolution_clock` (like + Emscripten when running in `AudioWorkletProcessor` context) * Required compilers to use libopenmpt: * Any **C89** / **C99** / **C11** compatible compiler should work with the C API as long as a **C99** compatible **stdint.h** is available. * Any **C++17** compatible compiler should work with the C++ API. * **J2B** support requires an inflate (deflate decompression) implementation: - * **zlib** - * **miniz** can be used internally if no zlib is available. - * Built-in **MO3** support requires: - * **libmpg123 >= 1.14.0** - * **libogg** - * **libvorbis** - * **libvorbisfile** - * Instead of libmpg123, **minimp3 by Lion (github.com/lieff)** can be used - internally to decode MP3 samples. - * Instead of libogg, libvorbis and libvorbisfile, **stb_vorbis** can be - used internally to decode Vorbis samples. + * **zlib** (or **miniz** can be used internally) + * **MO3** support requires: + * **libmpg123 >= 1.14.0** (or **minimp3 by Lion (github.com/lieff)** can + be used internally) + * **libogg**, **libvorbis**, and **libvorbisfile** (or **stb_vorbis** can + be used internally) * Building on Unix-like systems requires: * **GNU make** * **pkg-config** diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_impl.cpp b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_impl.cpp index 71cd67b60..7dea08c91 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_impl.cpp +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_impl.cpp @@ -1108,8 +1108,9 @@ double module_impl::set_position_seconds( double seconds ) { } m_sndFile->SetCurrentOrder( static_cast( subsong->start_order ) ); GetLengthType t = m_sndFile->GetLength( m_ctl_seek_sync_samples ? eAdjustSamplePositions : eAdjust, GetLengthTarget( seconds ).StartPos( static_cast( subsong->sequence ), static_cast( subsong->start_order ), static_cast( subsong->start_row ) ) ).back(); - m_sndFile->m_PlayState.m_nNextOrder = m_sndFile->m_PlayState.m_nCurrentOrder = t.lastOrder; - m_sndFile->m_PlayState.m_nNextRow = t.lastRow; + m_sndFile->m_PlayState.m_nNextOrder = m_sndFile->m_PlayState.m_nCurrentOrder = t.targetReached ? t.lastOrder : t.endOrder; + m_sndFile->m_PlayState.m_nNextRow = t.targetReached ? t.lastRow : t.endRow; + m_sndFile->m_PlayState.m_nTickCount = Util::MaxValueOfType(m_sndFile->m_PlayState.m_nTickCount) - 1; m_currentPositionSeconds = base_seconds + t.duration; return m_currentPositionSeconds; } diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h index edf57fc6d..bd41df699 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h @@ -19,7 +19,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 5 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 6 +#define OPENMPT_API_VERSION_PATCH 7 /*! \brief libopenmpt pre-release tag */ #define OPENMPT_API_VERSION_PREREL "" /*! \brief libopenmpt pre-release flag */ diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk index 5192b424f..cb808f105 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk @@ -1,8 +1,8 @@ LIBOPENMPT_VERSION_MAJOR=0 LIBOPENMPT_VERSION_MINOR=5 -LIBOPENMPT_VERSION_PATCH=6 +LIBOPENMPT_VERSION_PATCH=7 LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_LTVER_CURRENT=2 -LIBOPENMPT_LTVER_REVISION=6 +LIBOPENMPT_LTVER_REVISION=7 LIBOPENMPT_LTVER_AGE=2 diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerUMX.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerUMX.cpp index 53671c787..497cb1f3d 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerUMX.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerUMX.cpp @@ -77,8 +77,9 @@ bool UnpackUMX(std::vector &containerItems, FileReader &file, Con } std::vector classes; - classes.reserve(fileHeader.importCount); - for(uint32 i = 0; i < fileHeader.importCount && file.CanRead(4); i++) + const uint32 importCount = std::min(fileHeader.importCount.get(), mpt::saturate_cast(file.BytesLeft() / 4u)); + classes.reserve(importCount); + for(uint32 i = 0; i < importCount && file.CanRead(4); i++) { int32 objName = ReadUMXImportTableEntry(file, fileHeader.packageVersion); if(static_cast(objName) < names.size()) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_c67.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_c67.cpp index 9d5d70b82..16921f1c1 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_c67.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_c67.cpp @@ -168,6 +168,7 @@ bool CSoundFile::ReadC67(FileReader &file, ModLoadingFlags loadFlags) m_nSamples = 64; m_nChannels = 4 + 9; m_playBehaviour.set(kOPLBeatingOscillators); + m_SongFlags.set(SONG_IMPORTED); // Pan PCM channels only for(CHANNELINDEX chn = 0; chn < 4; chn++) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_dmf.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_dmf.cpp index 68a1a6231..64fe59efe 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_dmf.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_dmf.cpp @@ -934,10 +934,10 @@ bool CSoundFile::ReadDMF(FileReader &file, ModLoadingFlags loadFlags) file.Read(chunkHeader); uint32 chunkLength = chunkHeader.length, chunkSkip = 0; // When loop start was added to version 3, the chunk size was not updated... - if(fileHeader.version == 3 && chunkHeader.GetID() == DMFChunk::idSEQU && chunkLength < uint32_max - 2) + if(fileHeader.version == 3 && chunkHeader.GetID() == DMFChunk::idSEQU) chunkSkip = 2; // ...and when the loop end was added to version 4, it was also note updated! Luckily they fixed it in version 5. - else if(fileHeader.version == 4 && chunkHeader.GetID() == DMFChunk::idSEQU && chunkLength < uint32_max - 4) + else if(fileHeader.version == 4 && chunkHeader.GetID() == DMFChunk::idSEQU) chunkSkip = 4; // Earlier X-Tracker versions also write a garbage length for the SMPD chunk if samples are compressed. // I don't know when exactly this stopped, but I have no version 5-7 files to check (and no X-Tracker version that writes those versions). diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_gdm.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_gdm.cpp index 7171d8b06..b722efab3 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_gdm.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_gdm.cpp @@ -163,6 +163,7 @@ bool CSoundFile::ReadGDM(FileReader &file, ModLoadingFlags loadFlags) } InitializeGlobals(gdmFormatOrigin[fileHeader.originalFormat]); + m_SongFlags.set(SONG_IMPORTED); m_modFormat.formatName = U_("General Digital Music"); m_modFormat.type = U_("gdm"); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp index 89f281f73..66f07a02e 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp @@ -2086,19 +2086,11 @@ void CSoundFile::ReadMixPluginChunk(FileReader &file, SNDMIXPLUGIN &plugin) plugin.editorX = plugin.editorY = int32_min; // Plugin user data - const uint32 pluginDataChunkSize = file.ReadUint32LE(); - FileReader pluginDataChunk = file.ReadChunk(pluginDataChunkSize); + FileReader pluginDataChunk = file.ReadChunk(file.ReadUint32LE()); + plugin.pluginData.resize(mpt::saturate_cast(pluginDataChunk.BytesLeft())); + pluginDataChunk.ReadRaw(mpt::as_span(plugin.pluginData)); - if(pluginDataChunk.IsValid()) - { - plugin.pluginData.resize(pluginDataChunkSize); - pluginDataChunk.ReadRaw(plugin.pluginData.data(), pluginDataChunkSize); - } - - FileReader modularData = file.ReadChunk(file.ReadUint32LE()); - - //if dwMPTExtra is positive and there are dwMPTExtra bytes left in nPluginSize, we have some more data! - if(modularData.IsValid()) + if(FileReader modularData = file.ReadChunk(file.ReadUint32LE()); modularData.IsValid()) { while(modularData.CanRead(5)) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_itp.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_itp.cpp index db85fee72..b44ef5560 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_itp.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_itp.cpp @@ -160,6 +160,7 @@ bool CSoundFile::ReadITP(FileReader &file, ModLoadingFlags loadFlags) { return false; } + m_SongFlags.set(SONG_IMPORTED); if(songFlags & ITP_ITOLDEFFECTS) m_SongFlags.set(SONG_ITOLDEFFECTS); if(songFlags & ITP_ITCOMPATGXX) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp index 174768784..1ff0c39f5 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp @@ -399,40 +399,38 @@ struct MO3SampleChunk } while(carry); \ } -static bool UnpackMO3Data(FileReader &file, uint8 *dst, uint32 size) + +static bool UnpackMO3Data(FileReader &file, std::vector &uncompressed, const uint32 size) { if(!size) - { return false; - } uint16 data = 0; int8 carry = 0; // x86 carry (used to propagate the most significant bit from one byte to another) int32 strLen = 0; // length of previous string int32 strOffset; // string offset - uint8 *initDst = dst; - uint32 ebp, previousPtr = 0; - uint32 initSize = size; + uint32 previousPtr = 0; // Read first uncompressed byte - *dst++ = file.ReadUint8(); - size--; + uncompressed.push_back(file.ReadUint8()); + uint32 remain = size - 1; - while(size > 0) + while(remain > 0) { READ_CTRL_BIT; if(!carry) { // a 0 ctrl bit means 'copy', not compressed byte - if(!file.Read(*dst)) + if(uint8 b; file.Read(b)) + uncompressed.push_back(b); + else break; - dst++; - size--; + remain--; } else { // a 1 ctrl bit means compressed bytes are following - ebp = 0; // length adjustment - DECODE_CTRL_BITS; // read length, and if strLen > 3 (coded using more than 1 bits pair) also part of the offset value + uint8 lengthAdjust = 0; // length adjustment + DECODE_CTRL_BITS; // read length, and if strLen > 3 (coded using more than 1 bits pair) also part of the offset value strLen -= 3; if(strLen < 0) { @@ -442,17 +440,17 @@ static bool UnpackMO3Data(FileReader &file, uint8 *dst, uint32 size) } else { // LZ ptr in ctrl stream - uint8 b; - if(!file.Read(b)) + if(uint8 b; file.Read(b)) + strOffset = (strLen << 8) | b; // read less significant offset byte from stream + else break; - strOffset = (strLen << 8) | b; // read less significant offset byte from stream strLen = 0; strOffset = ~strOffset; if(strOffset < -1280) - ebp++; - ebp++; // length is always at least 1 + lengthAdjust++; + lengthAdjust++; // length is always at least 1 if(strOffset < -32000) - ebp++; + lengthAdjust++; previousPtr = strOffset; // save current Ptr } @@ -467,36 +465,33 @@ static bool UnpackMO3Data(FileReader &file, uint8 *dst, uint32 size) DECODE_CTRL_BITS; // decode length: 1 is the most significant bit, strLen += 2; // then first bit of each bits pairs (noted n1), until n0. } - strLen += ebp; // length adjustment - if(size >= static_cast(strLen) && strLen > 0) - { - // Copy previous string - if(strOffset >= 0 || static_cast(dst - initDst) + strOffset < 0) - { - break; - } - size -= strLen; - const uint8 *string = dst + strOffset; - while(strLen > 0) - { - *dst++ = *string++; - strLen--; - } - } else - { + strLen += lengthAdjust; // length adjustment + + if(remain < static_cast(strLen) || strLen <= 0) break; - } + if(strOffset >= 0 || -static_cast(uncompressed.size()) > strOffset) + break; + + // Copy previous string + // Need to do this in two steps as source and destination may overlap (e.g. strOffset = -1, strLen = 2 repeats last character twice) + uncompressed.insert(uncompressed.end(), strLen, 0); + remain -= strLen; + auto src = uncompressed.cend() - strLen + strOffset; + auto dst = uncompressed.end() - strLen; + do + { + strLen--; + *dst++ = *src++; + } while(strLen > 0); } } #ifdef MPT_BUILD_FUZZER // When using a fuzzer, we should not care if the decompressed buffer has the correct size. // This makes finding new interesting test cases much easier. - while(size-- > 0) - { - *dst++ = 0; - } + return true; +#else + return remain == 0; #endif // MPT_BUILD_FUZZER - return (dst - initDst) == static_cast(initSize); } @@ -742,7 +737,7 @@ static bool ValidateHeader(const MO3ContainerHeader &containerHeader) { return false; } - if(containerHeader.musicSize <= sizeof(MO3FileHeader)) + if(containerHeader.musicSize <= sizeof(MO3FileHeader) || containerHeader.musicSize >= uint32_max / 2u) { return false; } @@ -789,24 +784,25 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) } const uint8 version = containerHeader.version; - const uint32 musicSize = containerHeader.musicSize; - uint32 compressedSize = uint32_max; + uint32 compressedSize = uint32_max, reserveSize = 1024 * 1024; // Generous estimate based on biggest pre-v5 MO3s found in the wild (~350K music data) if(version >= 5) { // Size of compressed music chunk compressedSize = file.ReadUint32LE(); -#ifndef MPT_BUILD_FUZZER if(!file.CanRead(compressedSize)) - { return false; - } -#endif // !MPT_BUILD_FUZZER + // Generous estimate based on highest real-world compression ratio I found in a module (~20:1) + reserveSize = std::min(Util::MaxValueOfType(reserveSize) / 32u, compressedSize) * 32u; } - std::vector musicData(musicSize); - - if(!UnpackMO3Data(file, musicData.data(), musicSize)) + std::vector musicData; + // We don't always reserve the whole uncompressed size as claimed by the module to guard against broken files + // that e.g. claim that the uncompressed size is 1GB while the MO3 file itself is only 100 bytes. + // As the LZ compression used in MO3 doesn't allow for establishing a clear upper bound for the maximum size, + // this is probably the only sensible way we can prevent DoS due to huge allocations. + musicData.reserve(std::min(reserveSize, containerHeader.musicSize.get())); + if(!UnpackMO3Data(file, musicData, containerHeader.musicSize)) { return false; } @@ -849,6 +845,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) else SetType(MOD_TYPE_XM); + m_SongFlags.set(SONG_IMPORTED); if(fileHeader.flags & MO3FileHeader::linearSlides) m_SongFlags.set(SONG_LINEARSLIDES); if((fileHeader.flags & MO3FileHeader::s3mAmigaLimits) && m_nType == MOD_TYPE_S3M) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp index ebd124fe5..a4fcbaed7 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp @@ -1951,7 +1951,7 @@ bool CSoundFile::ReadICE(FileReader &file, ModLoadingFlags loadFlags) m_nMinPeriod = 14 * 4; m_nMaxPeriod = 3424 * 4; m_nSamplePreAmp = 64; - m_SongFlags.set(SONG_PT_MODE); + m_SongFlags.set(SONG_PT_MODE | SONG_IMPORTED); // Setup channel pan positions and volume SetupMODPanning(); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_stp.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_stp.cpp index fb4b38606..2beb381b3 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_stp.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_stp.cpp @@ -333,7 +333,9 @@ bool CSoundFile::ReadSTP(FileReader &file, ModLoadingFlags loadFlags) STPLoopList &loopList = loopInfo[actualSmp - 1]; loopList.clear(); - uint16 numLoops = file.ReadUint16BE(); + const uint16 numLoops = file.ReadUint16BE(); + if(!file.CanRead(numLoops * 8u)) + return false; loopList.reserve(numLoops); STPLoopInfo loop; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_uax.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_uax.cpp index ea55d36f3..2483535f2 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_uax.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_uax.cpp @@ -70,8 +70,9 @@ bool CSoundFile::ReadUAX(FileReader &file, ModLoadingFlags loadFlags) } std::vector classes; - classes.reserve(fileHeader.importCount); - for(uint32 i = 0; i < fileHeader.importCount && file.CanRead(4); i++) + const uint32 importCount = std::min(fileHeader.importCount.get(), mpt::saturate_cast(file.BytesLeft() / 4u)); + classes.reserve(importCount); + for(uint32 i = 0; i < importCount && file.CanRead(4); i++) { int32 objName = ReadUMXImportTableEntry(file, fileHeader.packageVersion); if(static_cast(objName) < names.size()) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h index 98870cdec..a74f2e3bc 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h @@ -244,26 +244,27 @@ enum DuplicateNoteAction : uint8 // Module flags - contains both song configuration and playback state... Use SONG_FILE_FLAGS and SONG_PLAY_FLAGS distinguish between the two. enum SongFlags { - SONG_FASTVOLSLIDES = 0x0002, // Old Scream Tracker 3.0 volume slides - SONG_ITOLDEFFECTS = 0x0004, // Old Impulse Tracker effect implementations - SONG_ITCOMPATGXX = 0x0008, // IT "Compatible Gxx" (IT's flag to behave more like other trackers w/r/t portamento effects) - SONG_LINEARSLIDES = 0x0010, // Linear slides vs. Amiga slides - SONG_PATTERNLOOP = 0x0020, // Loop current pattern (pattern editor) - SONG_STEP = 0x0040, // Song is in "step" mode (pattern editor) - SONG_PAUSED = 0x0080, // Song is paused (no tick processing, just rendering audio) - SONG_FADINGSONG = 0x0100, // Song is fading out - SONG_ENDREACHED = 0x0200, // Song is finished - SONG_FIRSTTICK = 0x1000, // Is set when the current tick is the first tick of the row - SONG_MPTFILTERMODE = 0x2000, // Local filter mode (reset filter on each note) - SONG_SURROUNDPAN = 0x4000, // Pan in the rear channels - SONG_EXFILTERRANGE = 0x8000, // Cutoff Filter has double frequency range (up to ~10Khz) - SONG_AMIGALIMITS = 0x10000, // Enforce amiga frequency limits - SONG_S3MOLDVIBRATO = 0x20000, // ScreamTracker 2 vibrato in S3M files - SONG_BREAKTOROW = 0x80000, // Break to row command encountered (internal flag, do not touch) - SONG_POSJUMP = 0x100000, // Position jump encountered (internal flag, do not touch) - SONG_PT_MODE = 0x200000, // ProTracker 1/2 playback mode - SONG_PLAYALLSONGS = 0x400000, // Play all subsongs consecutively (libopenmpt) - SONG_ISAMIGA = 0x800000, // Is an Amiga module and thus qualifies to be played using the Paula BLEP resampler + SONG_FASTVOLSLIDES = 0x02, // Old Scream Tracker 3.0 volume slides + SONG_ITOLDEFFECTS = 0x04, // Old Impulse Tracker effect implementations + SONG_ITCOMPATGXX = 0x08, // IT "Compatible Gxx" (IT's flag to behave more like other trackers w/r/t portamento effects) + SONG_LINEARSLIDES = 0x10, // Linear slides vs. Amiga slides + SONG_PATTERNLOOP = 0x20, // Loop current pattern (pattern editor) + SONG_STEP = 0x40, // Song is in "step" mode (pattern editor) + SONG_PAUSED = 0x80, // Song is paused (no tick processing, just rendering audio) + SONG_FADINGSONG = 0x0100, // Song is fading out + SONG_ENDREACHED = 0x0200, // Song is finished + SONG_FIRSTTICK = 0x1000, // Is set when the current tick is the first tick of the row + SONG_MPTFILTERMODE = 0x2000, // Local filter mode (reset filter on each note) + SONG_SURROUNDPAN = 0x4000, // Pan in the rear channels + SONG_EXFILTERRANGE = 0x8000, // Cutoff Filter has double frequency range (up to ~10Khz) + SONG_AMIGALIMITS = 0x1'0000, // Enforce amiga frequency limits + SONG_S3MOLDVIBRATO = 0x2'0000, // ScreamTracker 2 vibrato in S3M files + SONG_BREAKTOROW = 0x8'0000, // Break to row command encountered (internal flag, do not touch) + SONG_POSJUMP = 0x10'0000, // Position jump encountered (internal flag, do not touch) + SONG_PT_MODE = 0x20'0000, // ProTracker 1/2 playback mode + SONG_PLAYALLSONGS = 0x40'0000, // Play all subsongs consecutively (libopenmpt) + SONG_ISAMIGA = 0x80'0000, // Is an Amiga module and thus qualifies to be played using the Paula BLEP resampler + SONG_IMPORTED = 0x100'0000, // Song type does not represent actual module format / was imported from a different format (OpenMPT) }; DECLARE_FLAGSET(SongFlags) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp index 17cca1cb4..390312cd3 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp @@ -243,8 +243,6 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod { std::vector results; GetLengthType retval; - retval.startOrder = target.startOrder; - retval.startRow = target.startRow; // Are we trying to reach a certain pattern position? const bool hasSearchTarget = target.mode != GetLengthTarget::NoTarget && target.mode != GetLengthTarget::GetAllSubsongs; @@ -259,8 +257,18 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod // Temporary visited rows vector (so that GetLength() won't interfere with the player code if the module is playing at the same time) RowVisitor visitedRows(*this, sequence); - playState.m_nNextRow = playState.m_nRow = target.startRow; - playState.m_nNextOrder = playState.m_nCurrentOrder = target.startOrder; + // If sequence starts with some non-existent patterns, find a better start + { + ORDERINDEX startOrder = target.startOrder; + ROWINDEX startRow = target.startRow; + if(visitedRows.GetFirstUnvisitedRow(startOrder, startRow, true)) + { + target.startOrder = startOrder; + target.startRow = startRow; + } + } + retval.startRow = playState.m_nNextRow = playState.m_nRow = target.startRow; + retval.startOrder = playState.m_nNextOrder = playState.m_nCurrentOrder = target.startOrder; // Fast LUTs for commands that are too weird / complicated / whatever to emulate in sample position adjust mode. std::bitset forbiddenCommands; @@ -1317,6 +1325,7 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod m_opl->Patch(n, chn.pModSample->adlib); m_opl->NoteCut(n); } + chn.pCurrentSample = nullptr; } #ifndef NO_PLUGINS @@ -2928,10 +2937,7 @@ bool CSoundFile::ProcessEffects() { CheckNNA(nChn, instr, note, false); } - } - if(note) - { if(chn.nRestorePanOnNewNote > 0) { chn.nPan = (chn.nRestorePanOnNewNote & 0x7FFF) - 1; @@ -4699,7 +4705,14 @@ void CSoundFile::ExtendedS3MCommands(CHANNELINDEX nChn, ModCommand::PARAM param) // S2x: Set FineTune case 0x20: if(!m_SongFlags[SONG_FIRSTTICK]) break; - if(GetType() != MOD_TYPE_669) + if(GetType() == MOD_TYPE_IMF) + { + if(chn.nPeriod && chn.pModSample) + { + chn.nC5Speed = Util::muldivr(chn.pModSample->nC5Speed, 1712, ProTrackerTunedPeriods[param * 12]); + chn.nPeriod = GetPeriodFromNote(chn.nNote, 0, chn.nC5Speed); + } + } else if(GetType() != MOD_TYPE_669) { chn.nC5Speed = S3MFineTuneTable[param]; chn.nFineTune = MOD2XMFineTune(param); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp index 19d084f8a..3ea361d4b 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp @@ -455,15 +455,20 @@ bool CSoundFile::Create(FileReader file, ModLoadingFlags loadFlags) m_songMessage.assign(mpt::ToCharset(mpt::Charset::Locale, unarchiver.GetComment())); } #endif +#ifdef MODPLUG_TRACKER } MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) { MPT_EXCEPTION_DELETE_OUT_OF_MEMORY(e); + return false; +#endif // MODPLUG_TRACKER + } catch(const std::exception &) + { #ifdef MODPLUG_TRACKER return false; #else // libopenmpt already handles this. throw; -#endif // MODPLUG_TRACKER +#endif // MODPLUG_TRACKER } } else { @@ -961,10 +966,10 @@ void CSoundFile::LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow) m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed; m_PlayState.m_nPatternDelay = 0; m_PlayState.m_nFrameDelay = 0; - m_PlayState.m_nBufferCount = 0; m_PlayState.m_nNextPatStartRow = 0; m_SongFlags.set(SONG_PATTERNLOOP); } + m_PlayState.m_nBufferCount = 0; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/UMXTools.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/UMXTools.cpp index 895430d32..20c667870 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/UMXTools.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/UMXTools.cpp @@ -146,7 +146,7 @@ std::string ReadUMXNameTableEntry(FileReader &chunk, uint16 packageVersion) { return ""; } - name.reserve(length); + name.reserve(std::min(length, mpt::saturate_cast(chunk.BytesLeft()))); } // Simple zero-terminated string @@ -174,8 +174,9 @@ std::vector ReadUMXNameTable(FileReader &file, const UMXFileHeader { return names; } - names.reserve(fileHeader.nameCount); - for(uint32 i = 0; i < fileHeader.nameCount && file.CanRead(4); i++) + const uint32 nameCount = std::min(fileHeader.nameCount.get(), mpt::saturate_cast(file.BytesLeft() / 5u)); + names.reserve(nameCount); + for(uint32 i = 0; i < nameCount && file.CanRead(5); i++) { names.push_back(ReadUMXNameTableEntry(file, fileHeader.packageVersion)); }