commit:     0b20fe31ea2dfd92f1164aed4be4308a65d8fd9f
Author:     Lucio Sauer <watermanpaint <AT> posteo <DOT> net>
AuthorDate: Tue Sep 26 12:48:32 2023 +0000
Commit:     David Roman <davidroman96 <AT> gmail <DOT> com>
CommitDate: Tue Sep 26 12:51:14 2023 +0000
URL:        https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=0b20fe31

games-engines/easyrpg-player: backport use-after-free fix

Subsequently, unmask fluidsynth USE flag.

Signed-off-by: Lucio Sauer <watermanpaint <AT> posteo.net>

 .../easyrpg-player/easyrpg-player-0.8-r1.ebuild    | 193 +++++++++++++++++++++
 ...er-0.8-backport-use-after-free-fluidsynth.patch | 180 +++++++++++++++++++
 profiles/package.use.mask                          |   4 -
 3 files changed, 373 insertions(+), 4 deletions(-)

diff --git a/games-engines/easyrpg-player/easyrpg-player-0.8-r1.ebuild 
b/games-engines/easyrpg-player/easyrpg-player-0.8-r1.ebuild
new file mode 100644
index 0000000000..00866eabac
--- /dev/null
+++ b/games-engines/easyrpg-player/easyrpg-player-0.8-r1.ebuild
@@ -0,0 +1,193 @@
+# Copyright 2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+inherit cmake readme.gentoo-r1 xdg
+
+DESCRIPTION="RPG Maker 2000/2003 and EasyRPG games interpreter"
+HOMEPAGE="https://easyrpg.org/player/
+       https://github.com/EasyRPG/Player";
+SRC_URI="https://easyrpg.org/downloads/player/${PV}/${P}.tar.xz";
+
+# EasyRPG Player itself is GPLv3+.
+# The program's logos are CC-BY-SA 4.0.
+# --
+# The program bundles several 3rd-party libraries.
+#
+# FMMidi files - licensed under the 3-clause BSD license.
+# Since the files do not end up in the executable due to the configuration,
+# we ignore it.
+# - src/midisequencer.cpp
+# - src/midisequencer.h
+# - src/midisynth.cpp
+# - src/midisynth.h
+#
+# dr_wav files - licensed under (public-domain or MIT-0):
+# - src/external/dr_wav.h
+# rang files - licensed under the Unlicense:
+# - src/external/rang.hpp
+# Note that both dr_wav and rang are un-bundled and replaced with versions
+# provided by Gentoo packages. However, since these are header-only libraries,
+# their licenses are still included in the LICENSE variable.
+#
+# PicoJSON is used only for Emscripten builds (and unbundled before build).
+# --
+# The program also uses a couple of 3rd-party fonts. Since these are not
+# loaded at runtime, but rather baked into the executable at compile time,
+# their licenses are also added to the License tag.
+#
+# Baekmuk files - licensed under the Baekmuk license:
+# - resources/shinonome/korean/
+#
+# Shinonome files - released into the public domain:
+# - resources/shinonome/
+#
+# ttyp0 files - licensed under the ttyp0 license,
+# a variant of the MIT license:
+# - resources/ttyp0/
+#
+# WenQuanYi files - licensed under
+# GPLv2-or-later with Font Embedding Exception:
+# - resources/wenquanyi/
+#
+#
+# The upstream tarball contains also "Teenyicons", under the MIT license,
+# but those are used only for Emscripten builds.
+
+LICENSE="BAEKMUK CC-BY-4.0 GPL-2+-with-font-exception GPL-3+ public-domain
+       TTYP0 Unlicense || ( MIT-0 public-domain )"
+SLOT="0"
+
+KEYWORDS="~amd64"
+
+IUSE="doc fluidsynth harfbuzz +sound truetype +wildmidi"
+REQUIRED_USE="
+       fluidsynth? ( sound )
+       harfbuzz? ( truetype )
+       wildmidi? ( sound )
+"
+
+PATCHES=(
+       "${FILESDIR}"/${P}-backport-unbundle-dr_wav.patch
+       "${FILESDIR}"/${P}-backport-unbundle-rang.patch
+       "${FILESDIR}"/${P}-backport-update-for-fmt10.patch
+       "${FILESDIR}"/${P}-backport-use-after-free-fluidsynth.patch
+       "${FILESDIR}"/${P}-unbundle-picojson.patch
+)
+
+DEPEND="
+       dev-cpp/rang
+       >=dev-games/liblcf-${PV}
+       dev-libs/libfmt:=
+       media-libs/libpng:=
+       >=media-libs/libsdl2-2.0.5[joystick,sound?,video]
+       sys-libs/zlib
+       x11-libs/pixman
+       harfbuzz? ( media-libs/harfbuzz:=[truetype] )
+       truetype? ( media-libs/freetype:= )
+       sound? (
+                        media-libs/dr_wav
+                        media-libs/libsndfile
+                        media-libs/libvorbis
+                        media-libs/opusfile
+                        media-libs/speexdsp
+                        media-sound/mpg123
+                        media-libs/libxmp
+                        fluidsynth? ( media-sound/fluidsynth )
+                        wildmidi? ( media-sound/wildmidi )
+                        !fluidsynth? ( !wildmidi? ( media-libs/alsa-lib ) )
+                  )
+"
+RDEPEND="${DEPEND}
+       fluidsynth? ( media-sound/fluid-soundfont )
+"
+BDEPEND="virtual/pkgconfig
+       doc? (
+                  app-doc/doxygen
+                  media-gfx/graphviz[svg]
+                )
+"
+
+DOC_CONTENTS="
+EasyRPG Player chooses its library for MIDI output in increasing order:
+1. FluidSynth
+2. WildMIDI
+3. ALSA
+
+With all three enabled, it first tries to send MIDI messages to FluidSynth. If
+that fails it falls back to WildMIDI then to ALSA. Currently, the capability to
+find and configure a suitable MIDI client through ALSA is limited. It is
+recommended to enable one of the other backends, otherwise you are likely to
+have no sound.
+This package enables support for the ALSA backend only if the other two are
+disabled.
+
+For the requirements for suitable ALSA MIDI clients please reference the source
+code at src/platform/linux/midiout_device_alsa.cpp
+"
+
+src_prepare() {
+       # Install prebuilt manpage instead of rebuilding it conditionally.
+       sed -i -e "s/if(ASCIIDOCTOR_EXECUTABLE)/if(FALSE)/" \
+               -e "s/SUPPORT_AUDIO=1/SUPPORT_AUDIO=$(usex sound 1 0)/" 
CMakeLists.txt || die
+       cmake_src_prepare
+}
+
+src_configure() {
+       local mycmakeargs=(
+               -DPLAYER_BUILD_LIBLCF=OFF
+
+               # Use the first default choice
+               -DPLAYER_WITH_SPEEXDSP=$(usex sound)
+               -DPLAYER_WITH_SAMPLERATE=no
+
+               -DPLAYER_WITH_MPG123=$(usex sound)
+               -DPLAYER_WITH_OGGVORBIS=$(usex sound)
+               -DPLAYER_WITH_OPUS=$(usex sound)
+               -DPLAYER_WITH_XMP=$(usex sound)
+
+               # Avoid vendoring, use FluidSynth or WildMIDI (or ALSA) instead
+               -DPLAYER_ENABLE_FMMIDI=no
+               -DPLAYER_WITH_FLUIDSYNTH=$(usex fluidsynth)
+               -DPLAYER_WITH_WILDMIDI=$(usex wildmidi)
+               -DPLAYER_WITH_NATIVE_MIDI=$(usex sound $(usex fluidsynth no 
$(usex wildmidi no yes)) no)
+               # Serves as fallback when FluidSynth isn't found
+               -DPLAYER_WITH_FLUIDLITE=no
+               # Enable dr_wav for faster WAV decoding, fall back to libsndfile
+               -DPLAYER_ENABLE_DRWAV=$(usex sound)
+               -DPLAYER_WITH_LIBSNDFILE=$(usex sound)
+
+               # The text shaping engine is strictly dependent on the 
availability
+               # of TrueType fonts
+               -DPLAYER_WITH_HARFBUZZ=$(usex harfbuzz)
+               -DPLAYER_WITH_FREETYPE=$(usex harfbuzz yes $(usex truetype))
+       )
+       cmake_src_configure
+}
+
+src_compile() {
+       cmake_src_compile
+       if use doc; then
+               einfo "Building the documentation might take a while..."
+               cmake_build doc
+       fi
+}
+
+src_test() {
+       cmake_build check
+}
+
+src_install() {
+       cmake_src_install
+       if use doc; then
+               docinto /usr/share/doc/${PF}/html
+               dodoc -r "${BUILD_DIR}"/doc/*
+       fi
+       readme.gentoo_create_doc
+}
+
+pkg_postinst() {
+       xdg_pkg_postinst
+       readme.gentoo_print_elog
+}

diff --git 
a/games-engines/easyrpg-player/files/easyrpg-player-0.8-backport-use-after-free-fluidsynth.patch
 
b/games-engines/easyrpg-player/files/easyrpg-player-0.8-backport-use-after-free-fluidsynth.patch
new file mode 100644
index 0000000000..693ee2bd75
--- /dev/null
+++ 
b/games-engines/easyrpg-player/files/easyrpg-player-0.8-backport-use-after-free-fluidsynth.patch
@@ -0,0 +1,180 @@
+The following commit was fixed and backported from upstream. The fix adds
+a header to audio_generic_midiout.h to provide the missing definition
+of AudioDecoderMidi at compile time.
+Author: Lucio Sauer <[email protected]>
+
+https://github.com/EasyRPG/Player/issues/3079
+commit 7269d325035f547907ec352bff5d39bc611abc88
+Author: Ghabry <[email protected]>
+Date:   Fri Sep 22 20:45:19 2023 +0200
+
+    GenericAudio: Make static variables instance variables
+
+    This way they are destroyed when the DisplayUi is destroyed instead of 
when the process terminates.
+
+    Fixes a use-after-free in the Fluidsynth Decoder.
+--- a/src/audio_generic.cpp
++++ b/src/audio_generic.cpp
+@@ -20,33 +20,21 @@
+ #include <cstring>
+ #include <cassert>
+ #include <memory>
+-#include "audio_decoder_midi.h"
+ #include "audio_generic.h"
+-#include "audio_generic_midiout.h"
+-#include "filefinder.h"
+ #include "output.h"
+ 
+-GenericAudio::BgmChannel GenericAudio::BGM_Channels[nr_of_bgm_channels];
+-GenericAudio::SeChannel GenericAudio::SE_Channels[nr_of_se_channels];
+-bool GenericAudio::BGM_PlayedOnceIndicator;
+-
+-std::vector<int16_t> GenericAudio::sample_buffer = {};
+-std::vector<uint8_t> GenericAudio::scrap_buffer = {};
+-unsigned GenericAudio::scrap_buffer_size = 0;
+-std::vector<float> GenericAudio::mixer_buffer = {};
+-
+-std::unique_ptr<GenericAudioMidiOut> GenericAudio::midi_thread;
+-
+ GenericAudio::GenericAudio(const Game_ConfigAudio& cfg) : AudioInterface(cfg) 
{
+       int i = 0;
+       for (auto& BGM_Channel : BGM_Channels) {
+               BGM_Channel.id = i++;
+               BGM_Channel.decoder.reset();
++              BGM_Channel.instance = this;
+       }
+       i = 0;
+       for (auto& SE_Channel : SE_Channels) {
+               SE_Channel.id = i++;
+               SE_Channel.decoder.reset();
++              SE_Channel.instance = this;
+       }
+       BGM_PlayedOnceIndicator = false;
+       midi_thread.reset();
+@@ -492,8 +480,8 @@ void GenericAudio::BgmChannel::Stop() {
+       stopped = true;
+       if (midi_out_used) {
+               midi_out_used = false;
+-              midi_thread->GetMidiOut().Reset();
+-              midi_thread->GetMidiOut().Pause();
++              instance->midi_thread->GetMidiOut().Reset();
++              instance->midi_thread->GetMidiOut().Pause();
+       } else if (decoder) {
+               decoder.reset();
+       }
+@@ -503,16 +491,16 @@ void GenericAudio::BgmChannel::SetPaused(bool newPaused) 
{
+       paused = newPaused;
+       if (midi_out_used) {
+               if (newPaused) {
+-                      midi_thread->GetMidiOut().Pause();
++                      instance->midi_thread->GetMidiOut().Pause();
+               } else {
+-                      midi_thread->GetMidiOut().Resume();
++                      instance->midi_thread->GetMidiOut().Resume();
+               }
+       }
+ }
+ 
+ int GenericAudio::BgmChannel::GetTicks() const {
+       if (midi_out_used) {
+-              return midi_thread->GetMidiOut().GetTicks();
++              return instance->midi_thread->GetMidiOut().GetTicks();
+       } else if (decoder) {
+               return decoder->GetTicks();
+       }
+@@ -521,7 +509,7 @@ int GenericAudio::BgmChannel::GetTicks() const {
+ 
+ void GenericAudio::BgmChannel::SetFade(int fade) {
+       if (midi_out_used) {
+-              midi_thread->GetMidiOut().SetFade(0, 
std::chrono::milliseconds(fade));
++              instance->midi_thread->GetMidiOut().SetFade(0, 
std::chrono::milliseconds(fade));
+       } else if (decoder) {
+               decoder->SetFade(0, std::chrono::milliseconds(fade));
+       }
+@@ -529,7 +517,7 @@ void GenericAudio::BgmChannel::SetFade(int fade) {
+ 
+ void GenericAudio::BgmChannel::SetVolume(int volume) {
+       if (midi_out_used) {
+-              midi_thread->GetMidiOut().SetVolume(volume);
++              instance->midi_thread->GetMidiOut().SetVolume(volume);
+       } else if (decoder) {
+               decoder->SetVolume(volume);
+       }
+@@ -537,7 +525,7 @@ void GenericAudio::BgmChannel::SetVolume(int volume) {
+ 
+ void GenericAudio::BgmChannel::SetPitch(int pitch) {
+       if (midi_out_used) {
+-              midi_thread->GetMidiOut().SetPitch(pitch);
++              instance->midi_thread->GetMidiOut().SetPitch(pitch);
+       } else if (decoder) {
+               decoder->SetPitch(pitch);
+       }
+old mode 100644
+new mode 100755
+--- a/src/audio_generic.h
++++ b/src/audio_generic.h
+@@ -21,10 +21,9 @@
+ #include "audio.h"
+ #include "audio_secache.h"
+ #include "audio_decoder_base.h"
++#include "audio_generic_midiout.h"
+ #include <memory>
+ 
+-class GenericAudioMidiOut;
+-
+ /**
+  * A software implementation for handling EasyRPG Audio utilizing the
+  * AudioDecoder for BGM and AudioSeCache for fast SE playback.
+@@ -73,6 +72,7 @@ private:
+       struct BgmChannel {
+               int id;
+               std::unique_ptr<AudioDecoderBase> decoder;
++              GenericAudio* instance = nullptr;
+               bool paused;
+               bool stopped;
+               bool midi_out_used = false;
+@@ -87,6 +87,7 @@ private:
+       struct SeChannel {
+               int id;
+               std::unique_ptr<AudioDecoderBase> decoder;
++              GenericAudio* instance = nullptr;
+               bool paused;
+               bool stopped;
+       };
+@@ -103,17 +104,17 @@ private:
+       static constexpr unsigned nr_of_se_channels = 31;
+       static constexpr unsigned nr_of_bgm_channels = 2;
+ 
+-      static BgmChannel BGM_Channels[nr_of_bgm_channels];
+-      static SeChannel SE_Channels[nr_of_se_channels];
+-      static bool BGM_PlayedOnceIndicator;
+-      static bool Muted;
++      BgmChannel BGM_Channels[nr_of_bgm_channels];
++      SeChannel SE_Channels[nr_of_se_channels];
++      mutable bool BGM_PlayedOnceIndicator;
++      bool Muted;
+ 
+-      static std::vector<int16_t> sample_buffer;
+-      static std::vector<uint8_t> scrap_buffer;
+-      static unsigned scrap_buffer_size;
+-      static std::vector<float> mixer_buffer;
++      std::vector<int16_t> sample_buffer = {};
++      std::vector<uint8_t> scrap_buffer = {};
++      unsigned scrap_buffer_size = 0;
++      std::vector<float> mixer_buffer = {};
+ 
+-      static std::unique_ptr<GenericAudioMidiOut> midi_thread;
++      std::unique_ptr<GenericAudioMidiOut> midi_thread;
+ };
+ 
+ #endif
+--- a/src/audio_generic_midiout.h
++++ b/src/audio_generic_midiout.h
+@@ -19,6 +19,7 @@
+ #define EP_AUDIO_GENERIC_MIDITHREAD_H
+ 
+ #include <memory>
++#include "audio_decoder_midi.h"
+ #include "system.h"
+ 
+ class AudioDecoderMidi;

diff --git a/profiles/package.use.mask b/profiles/package.use.mask
index 32610624a9..fc5de3454a 100644
--- a/profiles/package.use.mask
+++ b/profiles/package.use.mask
@@ -3,10 +3,6 @@
 
 # New entries go on top.
 
-# Lucio Sauer<[email protected]> (2023-09-01)
-# Segfaults upon termination when run from inside a game folder.
-~games-engines/easyrpg-player-0.8 fluidsynth
-
 # Anna Vyalkova <[email protected]> (2023-06-17)
 # Broken docs build.
 dev-crystal/crikey doc

Reply via email to