[vlc-commits] [Git][videolan/vlc][master] 4 commits: medialibrary: Thumbnailer: fix double-free

Tristan Matthews (@tmatth) gitlab at videolan.org
Wed Jan 25 05:08:37 UTC 2023



Tristan Matthews pushed to branch master at VideoLAN / VLC


Commits:
a41743de by Alexandre Janniaux at 2023-01-25T04:29:36+00:00
medialibrary: Thumbnailer: fix double-free

The picture was referenced on the ThumbnailerCtx object, which release
it whenever one is not nullptr. However, after the changes in !3088,
commit 2ea2c7eb19122930877d42e981a6ef97e90a1f6e, the release policy for
the picture being exported has been fixed to ensure the picture is
consumed whatever the conversion case.

Ensure the picture won't be released twice by swapping it from the
ThumbnailerCtx object before exporting.

Fix #27749

- - - - -
603afb47 by Alexandre Janniaux at 2023-01-25T04:29:36+00:00
medialibrary: init ML before adding media

When calling VLC_ML_NEW_EXTERNAL_MEDIA or VLC_ML_NEW_STREAM, the
medialibrary must be initialized because the priority context is
acquired, just list for the VLC_ML_GENERATE_THUMBNAIL request.

Ensure the medialibrary is initialized at the same location as other
queries like this.

- - - - -
4791527a by Alexandre Janniaux at 2023-01-25T04:29:36+00:00
medialibrary: dump location path for medialibrary

The location helps determine where the user loaded the medialibrary
from.

- - - - -
277d7311 by Alexandre Janniaux at 2023-01-25T04:29:36+00:00
test: medialibrary: check that thumbnailing works

The test creates a libvlc instance with a medialibrary and check that
the medialibrary can generate a mock thumbnail for a given mock:// URL
with different parameters.

Multiple improvements can be done from here: in particular, the
medialibrary will insist in loading its discovery modules, whereas we
only need to check whether the thumbnailing work in this current test.
Some work needs to be done to evaluate whether it's interesting enough
to cut those discovery modules out for this test or extend the scenario
to other cases like testing those discovery modules.

Regression testing from #27749

- - - - -


4 changed files:

- modules/misc/medialibrary/Thumbnailer.cpp
- modules/misc/medialibrary/medialibrary.cpp
- test/Makefile.am
- + test/modules/misc/medialibrary.c


Changes:

=====================================
modules/misc/medialibrary/Thumbnailer.cpp
=====================================
@@ -83,8 +83,13 @@ bool Thumbnailer::generate( const medialibrary::IMedia&, const std::string& mrl,
     if ( ctx.thumbnail == nullptr )
         return false;
 
+    /* Both picture_Export and ThumbnailerCtx will release the thumbnail, so
+     * ensure that only picture_Export does. */
+    picture_t *thumbnail = nullptr;
+    std::swap(thumbnail, ctx.thumbnail);
+
     block_t* block;
-    if ( picture_Export( VLC_OBJECT( m_ml ), &block, nullptr, ctx.thumbnail,
+    if ( picture_Export( VLC_OBJECT( m_ml ), &block, nullptr, thumbnail,
                          VLC_CODEC_JPEG, desiredWidth, desiredHeight, true ) != VLC_SUCCESS )
         return false;
     auto blockPtr = vlc::wrap_cptr( block, &block_Release );


=====================================
modules/misc/medialibrary/medialibrary.cpp
=====================================
@@ -419,6 +419,8 @@ MediaLibrary* MediaLibrary::create( vlc_medialibrary_module_t* vlc_ml )
                         medialibrary::LogLevel::Debug : medialibrary::LogLevel::Warning;
     cfg.logger = std::make_shared<Logger>( VLC_OBJECT( vlc_ml ) );
 
+    msg_Dbg(VLC_OBJECT(vlc_ml), "Opening medialibrary from %s, db at %s",
+            dbPath.c_str(), mlFolderPath.c_str());
     auto ml = NewMediaLibrary( dbPath.c_str(), mlFolderPath.c_str(), true, &cfg );
     if ( !ml )
         return nullptr;
@@ -517,6 +519,8 @@ int MediaLibrary::Control( int query, va_list args )
         case VLC_ML_UNBAN_FOLDER:
         case VLC_ML_RELOAD_FOLDER:
         case VLC_ML_RESUME_BACKGROUND:
+        case VLC_ML_NEW_EXTERNAL_MEDIA:
+        case VLC_ML_NEW_STREAM:
         case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
         {
             /* These operations require the media library to be started


=====================================
test/Makefile.am
=====================================
@@ -38,6 +38,7 @@ check_PROGRAMS = \
 	test_src_misc_image \
 	test_src_video_output \
 	test_src_video_output_opengl \
+	test_modules_misc_medialibrary \
 	test_modules_packetizer_helpers \
 	test_modules_packetizer_hxxx \
 	test_modules_packetizer_h264 \
@@ -147,6 +148,9 @@ test_src_interface_dialog_SOURCES = src/interface/dialog.c
 test_src_interface_dialog_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_src_media_source_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_src_media_source_SOURCES = src/media_source/media_source.c
+
+test_modules_misc_medialibrary_SOURCES = modules/misc/medialibrary.c
+test_modules_misc_medialibrary_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_modules_packetizer_helpers_SOURCES = modules/packetizer/helpers.c
 test_modules_packetizer_helpers_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_modules_packetizer_hxxx_SOURCES = modules/packetizer/hxxx.c


=====================================
test/modules/misc/medialibrary.c
=====================================
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * medialibrary.c: test for the medialibrary code
+ *****************************************************************************
+ * Copyright (C) 2023 Videolabs
+ *
+ * Authors: Alexandre Janniaux <ajanni at videolabs.io>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Define a builtin module for mocked parts */
+#define MODULE_NAME test_misc_medialibrary
+#define MODULE_STRING "test_misc_medialibrary"
+#undef __PLUGIN__
+const char vlc_module_name[] = MODULE_STRING;
+
+#include "../../libvlc/test.h"
+
+#include <vlc/vlc.h>
+
+#include <vlc_common.h>
+#include <vlc_image.h>
+#include <vlc_picture.h>
+#include <vlc_plugin.h>
+#include <vlc_block.h>
+#include <vlc_codec.h>
+#include <vlc_filter.h>
+
+#include <vlc_media_library.h>
+#include <ftw.h>
+
+static int exitcode = 0;
+
+static void ValidateThumbnail(void *data, const vlc_ml_event_t *event)
+{
+    if (event->i_type != VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED)
+        return;
+
+    assert(event->media_thumbnail_generated.b_success);
+    vlc_sem_t *sem = data;
+    vlc_sem_post(sem);
+}
+
+static int OpenIntf(vlc_object_t *root)
+{
+    vlc_medialibrary_t *ml = vlc_ml_instance_get(root);
+    if (ml == NULL)
+    {
+        exitcode = 77;
+        return VLC_SUCCESS;
+    }
+
+    video_format_t fmt_in;
+    video_format_Init(&fmt_in, VLC_CODEC_RGBA);
+    fmt_in.i_width = fmt_in.i_visible_width = 800;
+    fmt_in.i_height = fmt_in.i_visible_height = 600;
+
+    video_format_t fmt_out;
+    video_format_Init(&fmt_out, VLC_CODEC_PNG);
+    fmt_out.i_width = fmt_out.i_visible_width = 800;
+    fmt_out.i_height = fmt_out.i_visible_height = 600;
+
+    picture_t *picture = picture_NewFromFormat(&fmt_in);
+    assert(picture != NULL);
+
+    #define MOCK_URL "mock://video_track_count=1;length=100000000;" \
+                     "video_width=800;video_height=600"
+    vlc_ml_media_t *media = vlc_ml_new_external_media(ml, MOCK_URL);
+
+    vlc_sem_t sem;
+    vlc_sem_init(&sem, 0);
+
+    vlc_ml_event_callback_t *listener =
+        vlc_ml_event_register_callback(ml, ValidateThumbnail, &sem);
+    vlc_ml_media_generate_thumbnail(ml, media->i_id,
+            VLC_ML_THUMBNAIL_SMALL, 800, 600, 0.f);
+
+    vlc_sem_wait(&sem);
+    vlc_ml_event_unregister_callback(ml, listener);
+
+    return VLC_SUCCESS;
+}
+
+/** Inject the mocked modules as a static plugin: **/
+vlc_module_begin()
+    set_callback(OpenIntf)
+    set_capability("interface", 0)
+vlc_module_end()
+
+/* Helper typedef for vlc_static_modules */
+typedef int (*vlc_plugin_cb)(vlc_set_cb, void*);
+
+VLC_EXPORT const vlc_plugin_cb vlc_static_modules[] = {
+    VLC_SYMBOL(vlc_entry),
+    NULL
+};
+
+static int cleanup_tmpdir(const char *dirpath, const struct stat *sb,
+                          int typeflag, struct FTW *ftwbuf)
+{
+    (void)sb; (void)typeflag; (void)ftwbuf;
+    return remove(dirpath);
+}
+
+int main()
+{
+    char template[] = "/tmp/vlc.test." MODULE_STRING ".XXXXXX";
+    const char *tempdir = mkdtemp(template);
+    if (tempdir == NULL)
+    {
+        assert(tempdir != NULL);
+        return -1;
+    }
+    fprintf(stderr, "Using XDG_DATA_HOME directory %s\n", tempdir);
+    setenv("XDG_DATA_HOME", tempdir, 1);
+
+    test_init();
+
+    const char * const args[] = {
+        "-vvv", "--vout=dummy", "--aout=dummy", "--text-renderer=dummy",
+        "--no-auto-preparse", "--media-library"
+    };
+
+    libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(args), args);
+
+    libvlc_add_intf(vlc, MODULE_STRING);
+    libvlc_playlist_play(vlc);
+
+    libvlc_release(vlc);
+
+    /* Remove temporary directory */
+    nftw(tempdir, cleanup_tmpdir, FOPEN_MAX, FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
+    return exitcode;
+}



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b024c077120ee14530fc2f95b31b997acad3b2ed...277d7311d1dc854c5c0a2fecfa3cdfab50a10b3c

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b024c077120ee14530fc2f95b31b997acad3b2ed...277d7311d1dc854c5c0a2fecfa3cdfab50a10b3c
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list