Bläddra i källkod

Ladybird+LibWeb+WebContent: Prevent out-of-bounds seeking audio elements

It's currently possible to seek to the total sample count of an audio
loader. We must limit seeking to one less than that count.

This mistake was duplicated in both AudioCodecPluginSerenity/Ladybird,
so the computation was moved to a helper in the base AudioCodecPlugin.
Timothy Flynn 2 år sedan
förälder
incheckning
bcd222cfae

+ 3 - 11
Ladybird/AudioCodecPluginLadybird.cpp

@@ -160,22 +160,14 @@ private:
                     paused = Paused::Yes;
                     paused = Paused::Yes;
                     break;
                     break;
 
 
-                case AudioTask::Type::Seek: {
+                case AudioTask::Type::Seek:
                     VERIFY(task.data.has_value());
                     VERIFY(task.data.has_value());
-                    auto position = *task.data;
+                    m_position = Web::Platform::AudioCodecPlugin::set_loader_position(m_loader, *task.data, m_duration, audio_output->format().sampleRate());
 
 
-                    auto duration = static_cast<double>(this->duration().to_milliseconds()) / 1000.0;
-                    position = position / duration * static_cast<double>(m_loader->total_samples());
-
-                    m_loader->seek(static_cast<int>(position)).release_value_but_fixme_should_propagate_errors();
-
-                    if (paused == Paused::Yes) {
-                        m_position = Web::Platform::AudioCodecPlugin::current_loader_position(m_loader, audio_output->format().sampleRate());
+                    if (paused == Paused::Yes)
                         Q_EMIT playback_position_updated(m_position);
                         Q_EMIT playback_position_updated(m_position);
-                    }
 
 
                     break;
                     break;
-                }
 
 
                 case AudioTask::Type::Volume:
                 case AudioTask::Type::Volume:
                     VERIFY(task.data.has_value());
                     VERIFY(task.data.has_value());

+ 12 - 0
Userland/Libraries/LibWeb/Platform/AudioCodecPlugin.cpp

@@ -40,6 +40,18 @@ ErrorOr<FixedArray<Audio::Sample>> AudioCodecPlugin::read_samples_from_loader(Au
     return FixedArray<Audio::Sample>::create(resampler.resample(buffer_or_error.release_value()).span());
     return FixedArray<Audio::Sample>::create(resampler.resample(buffer_or_error.release_value()).span());
 }
 }
 
 
+Duration AudioCodecPlugin::set_loader_position(Audio::Loader& loader, double position, Duration duration, size_t device_sample_rate)
+{
+    if (loader.total_samples() == 0)
+        return current_loader_position(loader, device_sample_rate);
+
+    auto duration_value = static_cast<double>(duration.to_milliseconds()) / 1000.0;
+    position = position / duration_value * static_cast<double>(loader.total_samples() - 1);
+
+    loader.seek(static_cast<int>(position)).release_value_but_fixme_should_propagate_errors();
+    return current_loader_position(loader, device_sample_rate);
+}
+
 Duration AudioCodecPlugin::current_loader_position(Audio::Loader const& loader, size_t device_sample_rate)
 Duration AudioCodecPlugin::current_loader_position(Audio::Loader const& loader, size_t device_sample_rate)
 {
 {
     auto samples_played = static_cast<double>(loader.loaded_samples());
     auto samples_played = static_cast<double>(loader.loaded_samples());

+ 1 - 0
Userland/Libraries/LibWeb/Platform/AudioCodecPlugin.h

@@ -24,6 +24,7 @@ public:
     virtual ~AudioCodecPlugin();
     virtual ~AudioCodecPlugin();
 
 
     static ErrorOr<FixedArray<Audio::Sample>> read_samples_from_loader(Audio::Loader&, size_t samples_to_load, size_t device_sample_rate);
     static ErrorOr<FixedArray<Audio::Sample>> read_samples_from_loader(Audio::Loader&, size_t samples_to_load, size_t device_sample_rate);
+    static Duration set_loader_position(Audio::Loader&, double position, Duration duration, size_t device_sample_rate);
     static Duration current_loader_position(Audio::Loader const&, size_t device_sample_rate);
     static Duration current_loader_position(Audio::Loader const&, size_t device_sample_rate);
 
 
     virtual void resume_playback() = 0;
     virtual void resume_playback() = 0;

+ 1 - 5
Userland/Services/WebContent/AudioCodecPluginSerenity.cpp

@@ -90,11 +90,7 @@ void AudioCodecPluginSerenity::set_volume(double volume)
 
 
 void AudioCodecPluginSerenity::seek(double position)
 void AudioCodecPluginSerenity::seek(double position)
 {
 {
-    auto duration = static_cast<double>(this->duration().to_milliseconds()) / 1000.0;
-    position = position / duration * static_cast<double>(m_loader->total_samples());
-
-    m_loader->seek(static_cast<int>(position)).release_value_but_fixme_should_propagate_errors();
-    m_position = current_loader_position(m_loader, m_device_sample_rate);
+    m_position = set_loader_position(m_loader, position, m_duration, m_device_sample_rate);
 
 
     if (on_playback_position_updated)
     if (on_playback_position_updated)
         on_playback_position_updated(m_position);
         on_playback_position_updated(m_position);