]> git.sesse.net Git - vlc/commitdiff
Fix error handling from module_list_get() (fixes #7500)
authorRémi Denis-Courmont <remi@remlab.net>
Fri, 28 Sep 2012 15:05:53 +0000 (18:05 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Fri, 28 Sep 2012 15:06:39 +0000 (18:06 +0300)
module_list_get() can return NULL, callers cannot assume that the table
is NULL-terminated (NULL is not NULL-terminated table).

12 files changed:
lib/audio.c
lib/core.c
modules/gui/qt4/components/complete_preferences.cpp
modules/gui/qt4/components/preferences_widgets.cpp
modules/gui/qt4/components/sout/profile_selector.cpp
modules/gui/qt4/dialogs/plugins.cpp
src/config/cmdline.c
src/config/core.c
src/config/file.c
src/config/help.c
src/modules/bank.c
src/modules/modules.c

index 5a5ebd380b4f479b7edc35b56ff8b3308e6f2e79..ba8f8534f752278f13e6bfdd8e03a52b860282db 100644 (file)
@@ -67,11 +67,11 @@ static audio_output_t *GetAOut( libvlc_media_player_t *mp )
 libvlc_audio_output_t *
         libvlc_audio_output_list_get( libvlc_instance_t *p_instance )
 {
-    VLC_UNUSED( p_instance );
+    size_t count;
+    module_t **module_list = module_list_get( &count );
     libvlc_audio_output_t *list = NULL;
-    module_t **module_list = module_list_get( NULL );
 
-    for (size_t i = 0; module_list[i]; i++)
+    for (size_t i = 0; i < count; i++)
     {
         module_t *module = module_list[i];
 
@@ -100,6 +100,7 @@ libvlc_audio_output_t *
     }
     module_list_free( module_list );
 
+    VLC_UNUSED( p_instance );
     return list;
 }
 
index a1a722a2bdb47713ca0de2b56a74bc8630c788c6..9fc0697958292b12f31d2a8fd167ec2d34b50d0c 100644 (file)
@@ -191,13 +191,13 @@ void libvlc_free( void *ptr )
 static libvlc_module_description_t *module_description_list_get(
                 libvlc_instance_t *p_instance, const char *capability )
 {
-    VLC_UNUSED( p_instance );
     libvlc_module_description_t *p_list = NULL,
                           *p_actual = NULL,
                           *p_previous = NULL;
-    module_t **module_list = module_list_get( NULL );
+    size_t count;
+    module_t **module_list = module_list_get( &count );
 
-    for (size_t i = 0; module_list[i]; i++)
+    for (size_t i = 0; i < count; i++)
     {
         module_t *p_module = module_list[i];
 
@@ -232,6 +232,7 @@ static libvlc_module_description_t *module_description_list_get(
     }
 
     module_list_free( module_list );
+    VLC_UNUSED( p_instance );
     return p_list;
 }
 
index 4c6658a29c4dc8d567c74c43ebe1689064d6be3e..f5c5b7aa8a1c85bd36393aff711c8057ebd19c8f 100644 (file)
@@ -193,11 +193,12 @@ PrefsTree::PrefsTree( intf_thread_t *_p_intf, QWidget *_parent ) :
     }
     module_config_free( p_config );
 
-
-    module_t **p_list = module_list_get( NULL );
+    size_t count;
+    module_t **p_list = module_list_get( &count );
     /* Build the tree of plugins */
-    for( size_t i = 0; (p_module = p_list[i]) != NULL; i++ )
+    for( size_t i = 0; i < count; i++ )
     {
+        p_module = p_list[i];
         // Main module excluded
         if( module_is_main( p_module) ) continue;
 
index 9031a00675358b3fe1032f232b57971318f867ad..a39e07a9ef9082ecdd76bc43937b968ec68460ee 100644 (file)
@@ -535,15 +535,16 @@ ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
 
 void ModuleConfigControl::finish( bool bycat )
 {
-    module_t *p_parser;
-
     combo->setEditable( false );
 
     /* build a list of available modules */
-    module_t **p_list = module_list_get( NULL );
+    size_t count;
+    module_t **p_list = module_list_get( &count );
     combo->addItem( qtr("Default") );
-    for( size_t i = 0; (p_parser = p_list[i]) != NULL; i++ )
+    for( size_t i = 0; i < count; i++ )
     {
+        module_t *p_parser = p_list[i];
+
         if( bycat )
         {
             if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
@@ -661,12 +662,13 @@ void ModuleListConfigControl::checkbox_lists( QString label, QString help, const
 
 void ModuleListConfigControl::finish( bool bycat )
 {
-    module_t *p_parser;
-
     /* build a list of available modules */
-    module_t **p_list = module_list_get( NULL );
-    for( size_t i = 0; (p_parser = p_list[i]) != NULL; i++ )
+    size_t count;
+    module_t **p_list = module_list_get( &count );
+    for( size_t i = 0; i < count; i++ )
     {
+        module_t *p_parser = p_list[i];
+
         if( bycat )
         {
             if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
index d86d7b44b0b177598f4750e94e8e9c74d4ea918c..418df14266986b1e985c630d480d1547ed874bbd 100644 (file)
@@ -440,15 +440,16 @@ void VLCProfileEditor::loadCapabilities()
 {
     size_t count;
     module_t **p_all = module_list_get (&count);
-    module_t *p_module;
 
     /* Parse the module list for capabilities and probe each of them */
-    for (size_t i = 0; (p_module = p_all[i]) != NULL; i++)
+    for (size_t i = 0; i < count; i++)
     {
-            if( module_provides( p_module, "sout mux" ) )
-                caps["muxers"].insert( module_get_object( p_module ) );
-//            else if ( module_provides( p_module, "encoder" ) )
-//                caps["encoders"].insert( module_get_object( p_module ) );
+         module_t *p_module = p_all[i];
+
+         if( module_provides( p_module, "sout mux" ) )
+             caps["muxers"].insert( module_get_object( p_module ) );
+//        else if ( module_provides( p_module, "encoder" ) )
+//            caps["encoders"].insert( module_get_object( p_module ) );
     }
     module_list_free (p_all);
 }
index 4d84ec9411065493026b62b43dfbff8dc7aed72d..2bc493896cc76ccf4858dfc3ff2ca47cdc6a5774 100644 (file)
@@ -130,11 +130,13 @@ PluginTab::PluginTab( intf_thread_t *p_intf_ )
 
 inline void PluginTab::FillTree()
 {
-    module_t **p_list = module_list_get( NULL );
-    module_t *p_module;
+    size_t count;
+    module_t **p_list = module_list_get( &count );
 
-    for( unsigned int i = 0; (p_module = p_list[i] ) != NULL; i++ )
+    for( unsigned int i = 0; i < count; i++ )
     {
+        module_t *p_module = p_list[i];
+
         QStringList qs_item;
         qs_item << qfu( module_get_name( p_module, true ) )
                 << qfu( module_get_capability( p_module ) )
index 258359934eedaae978089adfc8e2d7d6fea43076..12e92ba49711f109cebd0b6d8e25d44938b576e6 100644 (file)
@@ -59,7 +59,6 @@ int config_LoadCmdLine( vlc_object_t *p_this, int i_argc,
                         const char *ppsz_argv[], int *pindex )
 {
     int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
-    module_t *p_parser;
     struct vlc_option *p_longopts;
     const char **argv_copy = NULL;
 #define b_ignore_errors (pindex == NULL)
@@ -69,18 +68,23 @@ int config_LoadCmdLine( vlc_object_t *p_this, int i_argc,
     char *psz_shortopts;
 
     /* List all modules */
-    module_t **list = module_list_get (NULL);
+    size_t count;
+    module_t **list = module_list_get (&count);
 
     /*
      * Generate the longopts and shortopts structures used by getopt_long
      */
 
     i_opts = 0;
-    for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
+    for (size_t i = 0; i < count; i++)
+    {
         /* count the number of exported configuration options (to allocate
          * longopts). We also need to allocate space for two options when
          * dealing with boolean to allow for --foo and --no-foo */
+        module_t *p_parser = list[i];
+
         i_opts += p_parser->i_config_items + 2 * p_parser->i_bool_items;
+    }
 
     p_longopts = malloc( sizeof(*p_longopts) * (i_opts + 1) );
     if( p_longopts == NULL )
@@ -122,8 +126,9 @@ int config_LoadCmdLine( vlc_object_t *p_this, int i_argc,
 
     /* Fill the p_longopts and psz_shortopts structures */
     i_index = 0;
-    for (size_t i = 0; (p_parser = list[i]) != NULL; i++)
+    for (size_t i = 0; i < count; i++)
     {
+        module_t *p_parser = list[i];
         module_config_t *p_item, *p_end;
 
         if( !p_parser->i_config_items )
index 5c485f031625c719173bfc61a42827c702868f24..ff0636c2d7315bd65e5365552fa8ac9986cfb71c 100644 (file)
@@ -452,12 +452,9 @@ static struct
  */
 int config_SortConfig (void)
 {
-    size_t nmod;
+    size_t nmod, nconf = 0;
     module_t **mlist = module_list_get (&nmod);
-    if (unlikely(mlist == NULL))
-        return VLC_ENOMEM;
 
-    size_t nconf = 0;
     for (size_t i = 0; i < nmod; i++)
          nconf  += mlist[i]->confsize;
 
@@ -568,12 +565,14 @@ void config_Free (module_config_t *config, size_t confsize)
  *****************************************************************************/
 void config_ResetAll( vlc_object_t *p_this )
 {
-    VLC_UNUSED(p_this);
-    module_t *p_module;
-    module_t **list = module_list_get (NULL);
+    size_t count;
+    module_t **list = module_list_get (&count);
 
     vlc_rwlock_wrlock (&config_lock);
-    for (size_t j = 0; (p_module = list[j]) != NULL; j++)
+    for (size_t j = 0; j < count; j++)
+    {
+        module_t *p_module = list[j];
+
         for (size_t i = 0; i < p_module->confsize; i++ )
         {
             module_config_t *p_config = p_module->p_config + i;
@@ -591,7 +590,9 @@ void config_ResetAll( vlc_object_t *p_this )
                         strdupnull (p_config->orig.psz);
             }
         }
+    }
     vlc_rwlock_unlock (&config_lock);
 
     module_list_free (list);
+    VLC_UNUSED(p_this);
 }
index 9ad9537e30d4de172c33339fe1d18776e93fbfcf..8f422bf2a7497a6bb01b8890ffdd82ad4e5d7a57 100644 (file)
@@ -425,10 +425,11 @@ int config_SaveConfigFile (vlc_object_t *p_this)
     vlc_rwlock_rdlock (&config_lock);*/
 
     /* Look for the selected module, if NULL then save everything */
-    module_t **list = module_list_get (NULL);
-    module_t *p_parser;
-    for (int i = 0; (p_parser = list[i]) != NULL; i++)
+    size_t count;
+    module_t **list = module_list_get (&count);
+    for (size_t i = 0; i < count; i++)
     {
+        module_t *p_parser = list[i];
         module_config_t *p_item, *p_end;
 
         if( !p_parser->i_config_items )
index 89c5b8dbf6e6b51423cc519ce1ab95b18bffcbe3..3103a92d900bcd9cc365e9bb97da500da590fdb6 100644 (file)
@@ -293,9 +293,8 @@ static void Usage (vlc_object_t *p_this, char const *psz_search)
     }
 
     /* List all modules */
-    module_t **list = module_list_get (NULL);
-    if (!list)
-        return;
+    size_t count;
+    module_t **list = module_list_get (&count);
 
     /* Ugly hack to make sure that the help options always come first
      * (part 1) */
@@ -303,14 +302,14 @@ static void Usage (vlc_object_t *p_this, char const *psz_search)
         Usage( p_this, "help" );
 
     /* Enumerate the config for each module */
-    for (size_t i = 0; list[i]; i++)
+    for (size_t i = 0; i < count; i++)
     {
-        bool b_help_module;
         module_t *p_parser = list[i];
         module_config_t *p_item = NULL;
         module_config_t *p_section = NULL;
         module_config_t *p_end = p_parser->p_config + p_parser->confsize;
         const char *objname = module_get_object (p_parser);
+        bool b_help_module;
 
         if( psz_search &&
             ( b_strict ? strcmp( objname, psz_search )
@@ -722,8 +721,6 @@ static void Usage (vlc_object_t *p_this, char const *psz_search)
  *****************************************************************************/
 static void ListModules (vlc_object_t *p_this, bool b_verbose)
 {
-    module_t *p_parser;
-
     bool b_color = var_InheritBool( p_this, "color" );
 
     ShowConsole();
@@ -735,11 +732,13 @@ static void ListModules (vlc_object_t *p_this, bool b_verbose)
 #endif
 
     /* List all modules */
-    module_t **list = module_list_get (NULL);
+    size_t count;
+    module_t **list = module_list_get (&count);
 
     /* Enumerate each module */
-    for (size_t j = 0; (p_parser = list[j]) != NULL; j++)
+    for (size_t j = 0; j < count; j++)
     {
+        module_t *p_parser = list[j];
         const char *objname = module_get_object (p_parser);
         if( b_color )
             utf8_fprintf( stdout, GREEN"  %-22s "WHITE"%s\n"GRAY, objname,
index 8a2c5a7199ce5d891a9870af5ffc166b3071d0b1..5d99a6e76100291da78e9f1eeaad0732d81fd83e 100644 (file)
@@ -211,9 +211,9 @@ void module_list_free (module_t **list)
 
 /**
  * Gets the flat list of VLC modules.
- * @param n [OUT] pointer to the number of modules or NULL
- * @return NULL-terminated table of module pointers
- *         (release with module_list_free()), or NULL in case of error.
+ * @param n [OUT] pointer to the number of modules
+ * @return table of module pointers (release with module_list_free()),
+ *         or NULL in case of error (in that case, *n is zeroed).
  */
 module_t **module_list_get (size_t *n)
 {
@@ -222,13 +222,16 @@ module_t **module_list_get (size_t *n)
     module_t **tab = NULL;
     size_t i = 0;
 
+    assert (n != NULL);
+
     for (module_t *mod = modules.head; mod; mod = mod->next)
     {
          module_t **nt;
-         nt  = realloc (tab, (i + 2 + mod->submodule_count) * sizeof (*tab));
-         if (nt == NULL)
+         nt  = realloc (tab, (i + 1 + mod->submodule_count) * sizeof (*tab));
+         if (unlikely(nt == NULL))
          {
-             module_list_free (tab);
+             free (tab);
+             *n = 0;
              return NULL;
          }
 
@@ -236,10 +239,8 @@ module_t **module_list_get (size_t *n)
          tab[i++] = mod;
          for (module_t *subm = mod->submodule; subm; subm = subm->next)
              tab[i++] = subm;
-         tab[i] = NULL;
     }
-    if (n != NULL)
-        *n = i;
+    *n = i;
     return tab;
 }
 
index 7855c887dfe67eba1a3378a74bf0366d275d6097..a4ec9958b71464db4b1d1fd57e7d7043eb44c813 100644 (file)
@@ -199,8 +199,6 @@ module_t *vlc_module_load(vlc_object_t *p_this, const char *psz_capability,
                           const char *psz_name, bool b_strict,
                           vlc_activate_t probe, ...)
 {
-    module_list_t *p_list;
-    module_t *p_module;
     int i_shortcuts = 0;
     char *psz_shortcuts = NULL, *psz_var = NULL, *psz_alias = NULL;
     bool b_force_backup = p_this->b_force;
@@ -250,14 +248,14 @@ module_t *vlc_module_load(vlc_object_t *p_this, const char *psz_capability,
     }
 
     /* Sort the modules and test them */
-    size_t count;
-    module_t **p_all = module_list_get (&count);
-    p_list = xmalloc( count * sizeof( module_list_t ) );
+    size_t total, match = 0;
+    module_t **p_all = module_list_get (&total);
+    module_list_t *p_list = xmalloc( total * sizeof( module_list_t ) );
 
     /* Parse the module list for capabilities and probe each of them */
-    count = 0;
-    for (size_t i = 0; (p_module = p_all[i]) != NULL; i++)
+    for (size_t i = 0; i < total; i++)
     {
+        module_t *p_module = p_all[i];
         int i_shortcut_bonus = 0;
 
         /* Test that this module can do what we need */
@@ -304,27 +302,34 @@ module_t *vlc_module_load(vlc_object_t *p_this, const char *psz_capability,
 
 found_shortcut:
         /* Store this new module */
-        p_list[count].p_module = p_module;
-        p_list[count].i_score = p_module->i_score + i_shortcut_bonus;
-        p_list[count].b_force = i_shortcut_bonus && b_strict;
-        count++;
+        p_list[match].p_module = p_module;
+        p_list[match].i_score = p_module->i_score + i_shortcut_bonus;
+        p_list[match].b_force = i_shortcut_bonus && b_strict;
+        match++;
     }
 
     /* We can release the list, interesting modules are held */
     module_list_free (p_all);
 
+    if( match == 0 )
+    {
+        msg_Dbg( p_this, "no %s module matched \"%s\"",
+                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
+        return NULL; // shortcut
+    }
+
     /* Sort candidates by descending score */
-    qsort (p_list, count, sizeof (p_list[0]), modulecmp);
+    qsort (p_list, match, sizeof (p_list[0]), modulecmp);
     msg_Dbg( p_this, "looking for %s module: %zu candidate%s", psz_capability,
-             count, count == 1 ? "" : "s" );
+             match, match == 1 ? "" : "s" );
 
     /* Parse the linked list and use the first successful module */
+    module_t *p_module = NULL;
     va_list args;
 
     va_start(args, probe);
-    p_module = NULL;
 
-    for (size_t i = 0; (i < count) && (p_module == NULL); i++)
+    for (size_t i = 0; (i < match) && (p_module == NULL); i++)
     {
         module_t *p_cand = p_list[i].p_module;
 
@@ -372,9 +377,6 @@ found_shortcut:
         vlc_object_set_name( p_this, psz_alias ? psz_alias
                                                : module_get_object(p_module) );
     }
-    else if( count == 0 )
-        msg_Dbg( p_this, "no %s module matched \"%s\"",
-                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
     else
         msg_Dbg( p_this, "no %s module matching \"%s\" could be loaded",
                   psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
@@ -443,22 +445,25 @@ void module_unneed(vlc_object_t *obj, module_t *module)
  */
 module_t *module_find (const char *name)
 {
-    module_t **list, *module;
+    size_t count;
+    module_t **list = module_list_get (&count);
 
     assert (name != NULL);
-    list = module_list_get (NULL);
-    if (!list)
-        return NULL;
 
-    for (size_t i = 0; (module = list[i]) != NULL; i++)
+    for (size_t i = 0; i < count; i++)
     {
+        module_t *module = list[i];
+
         if (unlikely(module->i_shortcuts == 0))
             continue;
         if (!strcmp (module->pp_shortcuts[0], name))
-            break;
+        {
+            module_list_free (list);
+            return module;
+        }
     }
     module_list_free (list);
-    return module;
+    return NULL;
 }
 
 /**
@@ -483,19 +488,22 @@ bool module_exists (const char * psz_name)
  */
 module_t *module_find_by_shortcut (const char *psz_shortcut)
 {
-    module_t **list, *module;
+    size_t count;
+    module_t **list = module_list_get (&count);
 
-    list = module_list_get (NULL);
-    if (!list)
-        return NULL;
+    for (size_t i = 0; i < count; i++)
+    {
+        module_t *module = list[count];
 
-    for (size_t i = 0; (module = list[i]) != NULL; i++)
         for (size_t j = 0; j < module->i_shortcuts; j++)
             if (!strcmp (module->pp_shortcuts[j], psz_shortcut))
-                goto out;
-out:
+            {
+                module_list_free (list);
+                return module;
+            }
+    }
     module_list_free (list);
-    return module;
+    return NULL;
 }
 
 /**