Commit 74486e6b authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Fix error handling from module_list_get() (fixes #7500)

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