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

Subsequently, unmask fluidsynth USE flag.

Signed-off-by: Lucio Sauer <watermanpaint@posteo.net>
This commit is contained in:
Lucio Sauer
2023-09-26 14:48:32 +02:00
parent de1e7ef912
commit 0b20fe31ea
3 changed files with 373 additions and 4 deletions

View File

@@ -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
}

View File

@@ -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 <watermanpaint@posteo.net>
https://github.com/EasyRPG/Player/issues/3079
commit 7269d325035f547907ec352bff5d39bc611abc88
Author: Ghabry <gabriel+github@mastergk.de>
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;

View File

@@ -3,10 +3,6 @@
# New entries go on top.
# Lucio Sauer<watermanpaint@posteo.net> (2023-09-01)
# Segfaults upon termination when run from inside a game folder.
~games-engines/easyrpg-player-0.8 fluidsynth
# Anna Vyalkova <cyber+gentoo@sysrq.in> (2023-06-17)
# Broken docs build.
dev-crystal/crikey doc