]> git.sesse.net Git - vlc/blobdiff - src/modules/entry.c
auhal: fix memory corruption crash when device list changes (refs #8286)
[vlc] / src / modules / entry.c
index 989d5b9fe175b05bb77677da47d7a5f2631ef18a..2f63868a2e60b0bb52649871000b559fa61d65a3 100644 (file)
@@ -1,22 +1,22 @@
 /*****************************************************************************
  * entry.c : Callbacks for module entry point
  *****************************************************************************
- * Copyright (C) 2007 the VideoLAN team
+ * Copyright (C) 2007 VLC authors and VideoLAN
  * Copyright © 2007-2008 Rémi Denis-Courmont
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * 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 General Public License for more details.
+ * 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 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.
+ * 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
@@ -83,8 +83,14 @@ module_t *vlc_module_create (module_t *parent)
     return module;
 }
 
+/**
+ * Destroys a plug-in.
+ * @warning If the plug-in is loaded in memory, the handle will be leaked.
+ */
 void vlc_module_destroy (module_t *module)
 {
+    assert (!module->b_loaded || !module->b_unloadable);
+
     for (module_t *m = module->submodule, *next; m != NULL; m = next)
     {
         next = m->next;
@@ -139,8 +145,14 @@ static module_config_t *vlc_config_create (module_t *module, int type)
 }
 
 
-int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
+/**
+ * Callback for the plugin descriptor functions.
+ */
+static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
 {
+    module_t **pprimary = plugin;
+    module_t *module = tgt;
+    module_config_t *item = tgt;
     va_list ap;
     int ret = 0;
 
@@ -149,18 +161,20 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
     {
         case VLC_MODULE_CREATE:
         {
-            module_t **pp = va_arg (ap, module_t **);
+            module = *pprimary;
             module_t *submodule = vlc_module_create (module);
-
             if (unlikely(submodule == NULL))
             {
                 ret = -1;
                 break;
             }
 
-            *pp = submodule;
-            if (module == NULL)
+            *(va_arg (ap, module_t **)) = submodule;
+            if (*pprimary == NULL)
+            {
+                *pprimary = submodule;
                 break;
+            }
             /* Inheritance. Ugly!! */
             submodule->pp_shortcuts = xmalloc (sizeof (char **));
             submodule->pp_shortcuts[0] = strdup_null (module->pp_shortcuts[0]);
@@ -176,9 +190,14 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
         {
             int type = va_arg (ap, int);
             module_config_t **pp = va_arg (ap, module_config_t **);
-            *pp = vlc_config_create (module, type);
-            if (*pp == NULL)
+
+            item = vlc_config_create (*pprimary, type);
+            if (unlikely(item == NULL))
+            {
                 ret = -1;
+                break;
+            }
+            *pp = item;
             break;
         }
 
@@ -300,18 +319,16 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
 
         case VLC_CONFIG_RANGE:
         {
-            if (IsConfigIntegerType (item->i_type)
-             || !CONFIG_ITEM(item->i_type))
-            {
-                item->min.i = va_arg (ap, int64_t);
-                item->max.i = va_arg (ap, int64_t);
-            }
-            else
             if (IsConfigFloatType (item->i_type))
             {
                 item->min.f = va_arg (ap, double);
                 item->max.f = va_arg (ap, double);
             }
+            else
+            {
+                item->min.i = va_arg (ap, int64_t);
+                item->max.i = va_arg (ap, int64_t);
+            }
             break;
         }
 
@@ -342,14 +359,6 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
             item->i_short = va_arg (ap, int);
             break;
 
-        case VLC_CONFIG_OLDNAME:
-        {
-            const char *oldname = va_arg (ap, const char *);
-            assert (item->psz_oldname == NULL);
-            item->psz_oldname = oldname ? strdup (oldname) : NULL;
-            break;
-        }
-
         case VLC_CONFIG_SAFE:
             item->b_safe = true;
             break;
@@ -368,86 +377,51 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
         {
             size_t len = va_arg (ap, size_t);
 
+            assert (item->list_count == 0); /* cannot replace choices */
+            assert (item->list.psz_cb == NULL);
+            if (len == 0)
+                break; /* nothing to do */
             /* Copy values */
             if (IsConfigIntegerType (item->i_type))
             {
                 const int *src = va_arg (ap, const int *);
-                int *dst = malloc (sizeof (int) * (len + 1));
-
-                if (dst != NULL)
-                {
-                    memcpy (dst, src, sizeof (int) * len);
-                    dst[len] = 0;
-                }
-                item->pi_list = dst;
+                int *dst = xmalloc (sizeof (int) * len);
+
+                memcpy (dst, src, sizeof (int) * len);
+                item->list.i = dst;
             }
             else
             if (IsConfigStringType (item->i_type))
             {
                 const char *const *src = va_arg (ap, const char *const *);
-                char **dst = malloc (sizeof (char *) * (len + 1));
-
-                if (dst != NULL)
-                {
-                    for (size_t i = 0; i < len; i++)
-                        dst[i] = src[i] ? strdup (src[i]) : NULL;
-                    dst[len] = NULL;
-                }
-                item->ppsz_list = dst;
+                char **dst = xmalloc (sizeof (char *) * len);
+
+                for (size_t i = 0; i < len; i++)
+                     dst[i] = src[i] ? strdup (src[i]) : NULL;
+                item->list.psz = dst;
             }
             else
                 break;
 
             /* Copy textual descriptions */
             const char *const *text = va_arg (ap, const char *const *);
-            if (text != NULL)
-            {
-                char **dtext = malloc (sizeof (char *) * (len + 1));
-                if( dtext != NULL )
-                {
-                    for (size_t i = 0; i < len; i++)
-                        dtext[i] = text[i] ? strdup (text[i]) : NULL;
-                    dtext[len] = NULL;
-                }
-                item->ppsz_list_text = dtext;
-            }
-            else
-                item->ppsz_list_text = NULL;
-
-            item->i_list = len;
-            item->pf_update_list = va_arg (ap, vlc_callback_t);
+            char **dtext = xmalloc (sizeof (char *) * (len + 1));
+            for (size_t i = 0; i < len; i++)
+                dtext[i] = text[i] ? strdup (text[i]) : NULL;
+            item->list_text = dtext;
+            item->list_count = len;
             break;
         }
 
-        case VLC_CONFIG_ADD_ACTION:
-        {
-            vlc_callback_t cb = va_arg (ap, vlc_callback_t), *tabcb;
-            const char *name = va_arg (ap, const char *);
-            char **tabtext;
-
-            tabcb = realloc (item->ppf_action,
-                             (item->i_action + 2) * sizeof (cb));
-            if (tabcb == NULL)
-                break;
-            item->ppf_action = tabcb;
-            tabcb[item->i_action] = cb;
-            tabcb[item->i_action + 1] = NULL;
-
-            tabtext = realloc (item->ppsz_action_text,
-                               (item->i_action + 2) * sizeof (name));
-            if (tabtext == NULL)
-                break;
-            item->ppsz_action_text = tabtext;
-
-            if (name)
-                tabtext[item->i_action] = strdup (name);
+        case VLC_CONFIG_LIST_CB:
+            if (IsConfigIntegerType (item->i_type))
+               item->list.i_cb = va_arg (ap, vlc_integer_list_cb);
             else
-                tabtext[item->i_action] = NULL;
-            tabtext[item->i_action + 1] = NULL;
-
-            item->i_action++;
+            if (IsConfigStringType (item->i_type))
+               item->list.psz_cb = va_arg (ap, vlc_string_list_cb);
+            else
+                break;
             break;
-        }
 
         default:
             fprintf (stderr, "LibVLC: unknown module property %d\n", propid);
@@ -459,3 +433,19 @@ int vlc_plugin_set (module_t *module, module_config_t *item, int propid, ...)
     va_end (ap);
     return ret;
 }
+
+/**
+ * Runs a plug-in descriptor. This loads the plug-in meta-data in memory.
+ */
+module_t *vlc_plugin_describe (vlc_plugin_cb entry)
+{
+    module_t *module = NULL;
+
+    if (entry (vlc_plugin_setter, &module) != 0)
+    {
+        if (module != NULL) /* partially initialized plug-in... */
+            vlc_module_destroy (module);
+        module = NULL;
+    }
+    return module;
+}