FIx potential segfault (CID 168)
[vlc.git] / modules / misc / osd / simple.c
index d14ed10..d618da1 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * simple.c - The OSD Menu simple parser code.
  *****************************************************************************
- * Copyright (C) 2005-2007 M2X
- * $Id$
+ * Copyright (C) 2005-2008 M2X
+ * $Id$
  *
  * Authors: Jean-Paul Saman
  *
  * Preamble
  *****************************************************************************/
 
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
 #include <vlc_vout.h>
 #include <vlc_config.h>
 
 #include <vlc_osd.h>
 #include <vlc_charset.h>
 
+#include <limits.h>
+
+#include "osd_menu.h"
+
+int osd_parser_simpleOpen( vlc_object_t *p_this );
+
 /*****************************************************************************
- * osd_ConfigLoader: Load and parse osd text configurationfile
+ * Simple parser open function
  *****************************************************************************/
-int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
+int osd_parser_simpleOpen( vlc_object_t *p_this )
 {
-    osd_menu_t     *p_menu = (osd_menu_t *) p_this->p_menu;
+    osd_menu_t     *p_menu = (osd_menu_t *) p_this;
     osd_button_t   *p_current = NULL; /* button currently processed */
     osd_button_t   *p_prev = NULL;    /* previous processed button */
 
-#define MAX_FILE_PATH 256
     FILE       *fd = NULL;
     int        result = 0;
 
+    if( !p_menu ) return VLC_ENOOBJ;
+
     msg_Dbg( p_this, "opening osdmenu definition file %s", p_menu->psz_file );
     fd = utf8_fopen( p_menu->psz_file, "r" );
     if( !fd )
     {
-        msg_Err( p_this, "failed to open osdmenu definition file %s", p_menu->psz_file );
+        msg_Err( p_this, "failed to open osdmenu definition file %s",
+                p_menu->psz_file );
         return VLC_EGENERIC;
     }
 
@@ -60,7 +72,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
     {
         char action[25] = "";
         char cmd[25] = "";
-        char path[MAX_FILE_PATH] = "";
+        char path[PATH_MAX] = "";
         char *psz_path = NULL;
         size_t i_len = 0;
         long pos = 0;
@@ -74,15 +86,18 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
             /* psz_path is not null and therefor &path[0] cannot be NULL
              * it might be null terminated.
              */
-            strncpy( &path[0], psz_path, MAX_FILE_PATH );
+            strncpy( &path[0], psz_path, PATH_MAX );
             free( psz_path );
             psz_path = NULL;
         }
         /* NULL terminate before asking the length of path[] */
-        path[MAX_FILE_PATH-1] = '\0';
+        path[PATH_MAX-1] = '\0';
         i_len = strlen(&path[0]);
-        if( i_len == MAX_FILE_PATH )
-            i_len--; /* truncate to prevent buffer overflow */
+        /* Protect against buffer overflow:
+         * max index is PATH_MAX-1 and we increment by 1 after
+         * so PATH_MAX-2 is the bigest we can have */
+        if( i_len > PATH_MAX - 2 )
+            i_len = PATH_MAX - 2;
 #if defined(WIN32) || defined(UNDER_CE)
         if( (i_len > 0) && path[i_len] != '\\' )
             path[i_len] = '\\';
@@ -96,14 +111,14 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
         msg_Dbg( p_this, "osdmenu dir %s", &path[0] );
 
         if( i_len == 0 )
-            *p_menu = osd_MenuNew( *p_menu, NULL, 0, 0 );
+            p_menu = osd_MenuNew( p_menu, NULL, 0, 0 );
         else
-            *p_menu = osd_MenuNew( *p_menu, &path[0], 0, 0 );
+            p_menu = osd_MenuNew( p_menu, &path[0], 0, 0 );
 
         /* Peek for 'style' argument */
         pos = ftell( fd );
         if( pos < 0 )
-                goto error;
+            goto error;
 
         result = fscanf(fd, "%24s %24s", &cmd[0], &action[0] );
         if( result == 0 || result == EOF )
@@ -114,11 +129,11 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
         {
             if( strncmp( &action[0], "default", 7) == 0 )
             {
-                (*p_menu)->i_style = OSD_MENU_STYLE_SIMPLE;
+                p_menu->i_style = OSD_MENU_STYLE_SIMPLE;
             }
             else if( strncmp( &action[0], "concat", 6) == 0 )
             {
-                (*p_menu)->i_style = OSD_MENU_STYLE_CONCAT;
+                p_menu->i_style = OSD_MENU_STYLE_CONCAT;
             }
         }
         else
@@ -129,7 +144,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
         }
     }
 
-    if( !*p_menu )
+    if( !p_menu )
         goto error;
 
     /* read successive lines */
@@ -142,7 +157,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
         char action[25] = "";
         char state[25]  = "";
         char file[256]  = "";
-        char path[512]  = "";
+        char path[PATH_MAX]  = "";
         int  i_x = 0;
         int  i_y = 0;
 
@@ -161,7 +176,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
         if( p_prev )
             p_prev->p_next = p_current;
         else
-            (*p_menu)->p_button = p_current;
+            p_menu->p_button = p_current;
         p_current->p_prev = p_prev;
 
         /* parse all states */
@@ -197,7 +212,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                 {
                     if( strncmp( &type[0], "volume", 6 ) == 0 )
                     {
-                        (*p_menu)->p_state->p_volume = p_up;
+                        p_menu->p_state->p_volume = p_up;
                         msg_Dbg( p_this, " + type=%s", &type[0] );
                     }
                 }
@@ -212,7 +227,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                     osd_state_t   *p_range_prev = NULL;    /* previous state processed range */
                     int i_index = 0;
 
-                    p_up->b_range = VLC_TRUE;
+                    p_up->b_range = true;
 
                     result = fscanf( fd, "\t%24s", &action[0] );
                     if( result == 0 )
@@ -223,9 +238,9 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                         goto error;
 
                     msg_Dbg( p_this, " + (menu up) hotkey down %s, file=%s%s",
-                             &action[0], (*p_menu)->psz_path, &file[0] );
+                             &action[0], p_menu->psz_path, &file[0] );
 
-                    if( p_up->psz_action_down ) free( p_up->psz_action_down );
+                    free( p_up->psz_action_down );
                     p_up->psz_action_down = strdup( &action[0] );
 
                     /* Parse range contstruction :
@@ -245,23 +260,37 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
 
                         p_range_prev = p_range_current;
 
-                        if( (*p_menu)->psz_path )
+                        if( p_menu->psz_path )
                         {
-                            size_t i_path_size = strlen( (*p_menu)->psz_path );
+                            size_t i_path_size = strlen( p_menu->psz_path );
                             size_t i_file_size = strlen( &file[0] );
 
-                            strncpy( &path[0], (*p_menu)->psz_path, i_path_size );
-                            strncpy( &path[i_path_size], &file[0], 512 - (i_path_size + i_file_size) );
+                            if( (i_path_size + i_file_size >= PATH_MAX) ||
+                                (i_path_size >= PATH_MAX) )
+                                goto error;
+
+                            strncpy( &path[0], p_menu->psz_path, i_path_size );
+                            strncpy( &path[i_path_size], &file[0],
+                                     PATH_MAX - (i_path_size + i_file_size) );
                             path[ i_path_size + i_file_size ] = '\0';
 
-                            p_range_current = osd_StateNew( p_this, &path[0], "pressed" );
+                            p_range_current = osd_StateNew( p_menu, &path[0], "pressed" );
                         }
                         else /* absolute paths are used. */
-                            p_range_current = osd_StateNew( p_this, &file[0], "pressed" );
+                            p_range_current = osd_StateNew( p_menu, &file[0], "pressed" );
 
-                        if( !p_range_current || !p_range_current->p_pic )
+                        if( !p_range_current )
                             goto error;
 
+                        if( !p_range_current->p_pic )
+                        {
+                            osd_StatesFree( p_menu, p_range_current );
+                            goto error;
+                        }
+
+                        p_range_current->i_x = i_x;
+                        p_range_current->i_y = i_y;
+
                         /* increment the number of ranges for this button */
                         p_up->i_ranges++;
 
@@ -272,8 +301,8 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                         p_range_current->p_prev = p_range_prev;
 
                         msg_Dbg( p_this, "  |- range=%d, file=%s%s",
-                                p_up->i_ranges,
-                                (*p_menu)->psz_path, &file[0] );
+                                 p_up->i_ranges,
+                                 p_menu->psz_path, &file[0] );
                     }
                     if( i_index > 0 )
                     {
@@ -309,7 +338,7 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                 osd_state_t   *p_range_prev = NULL;    /* previous state processed range */
                 int i_index = 0;
 
-                p_current->b_range = VLC_TRUE;
+                p_current->b_range = true;
 
                 result = fscanf( fd, "\t%24s", &action[0] );
                 if( result == 0 )
@@ -319,8 +348,9 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                 if( result == 0 )
                     goto error;
 
-                msg_Dbg( p_this, " + hotkey down %s, file=%s%s", &action[0], (*p_menu)->psz_path, &file[0] );
-                if( p_current->psz_action_down ) free( p_current->psz_action_down );
+                msg_Dbg( p_this, " + hotkey down %s, file=%s%s", 
+                         &action[0], p_menu->psz_path, &file[0] );
+                free( p_current->psz_action_down );
                 p_current->psz_action_down = strdup( &action[0] );
 
                 /* Parse range contstruction :
@@ -340,23 +370,37 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
 
                     p_range_prev = p_range_current;
 
-                    if( (*p_menu)->psz_path )
+                    if( p_menu->psz_path )
                     {
-                        size_t i_path_size = strlen( (*p_menu)->psz_path );
+                        size_t i_path_size = strlen( p_menu->psz_path );
                         size_t i_file_size = strlen( &file[0] );
 
-                        strncpy( &path[0], (*p_menu)->psz_path, i_path_size );
-                        strncpy( &path[i_path_size], &file[0], 512 - (i_path_size + i_file_size) );
+                        if( (i_path_size + i_file_size >= PATH_MAX) ||
+                            (i_path_size >= PATH_MAX) )
+                            goto error;
+
+                        strncpy( &path[0], p_menu->psz_path, i_path_size );
+                        strncpy( &path[i_path_size], &file[0],
+                                 PATH_MAX - (i_path_size + i_file_size) );
                         path[ i_path_size + i_file_size ] = '\0';
 
-                        p_range_current = osd_StateNew( p_this, &path[0], "pressed" );
+                        p_range_current = osd_StateNew( p_menu, &path[0], "pressed" );
                     }
                     else /* absolute paths are used. */
-                        p_range_current = osd_StateNew( p_this, &file[0], "pressed" );
+                        p_range_current = osd_StateNew( p_menu, &file[0], "pressed" );
 
-                    if( !p_range_current || !p_range_current->p_pic )
+                    if( !p_range_current )
                         goto error;
 
+                    if( !p_range_current->p_pic )
+                    {
+                        osd_StatesFree( p_menu, p_range_current );
+                        goto error;
+                    }
+
+                    p_range_current->i_x = i_x;
+                    p_range_current->i_y = i_y;
+
                     /* increment the number of ranges for this button */
                     p_current->i_ranges++;
 
@@ -367,8 +411,8 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                     p_range_current->p_prev = p_range_prev;
 
                     msg_Dbg( p_this, "  |- range=%d, file=%s%s",
-                            p_current->i_ranges,
-                            (*p_menu)->psz_path, &file[0] );
+                             p_current->i_ranges,
+                             p_menu->psz_path, &file[0] );
                 }
                 if( i_index > 0 )
                 {
@@ -407,30 +451,45 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
                 goto error;
             }
 
-            if( (*p_menu)->psz_path )
+            if( p_menu->psz_path )
             {
-                size_t i_path_size = strlen( (*p_menu)->psz_path );
+                size_t i_path_size = strlen( p_menu->psz_path );
                 size_t i_file_size = strlen( &file[0] );
 
-                strncpy( &path[0], (*p_menu)->psz_path, i_path_size );
-                strncpy( &path[i_path_size], &file[0], 512 - (i_path_size + i_file_size) );
+                if( (i_path_size + i_file_size >= PATH_MAX) ||
+                    (i_path_size >= PATH_MAX) )
+                    goto error;
+
+                strncpy( &path[0], p_menu->psz_path, i_path_size );
+                strncpy( &path[i_path_size], &file[0],
+                         PATH_MAX - (i_path_size + i_file_size) );
                 path[ i_path_size + i_file_size ] = '\0';
 
-                p_state_current = osd_StateNew( p_this, &path[0], &state[0] );
+                p_state_current = osd_StateNew( p_menu, &path[0], &state[0] );
             }
             else /* absolute paths are used. */
-                p_state_current = osd_StateNew( p_this, &file[0], &state[0] );
+                p_state_current = osd_StateNew( p_menu, &file[0], &state[0] );
 
-            if( !p_state_current || !p_state_current->p_pic )
+            if( !p_state_current )
                 goto error;
 
+            if( !p_state_current->p_pic )
+            {
+                osd_StatesFree( p_menu, p_state_current );
+                goto error;
+            }
+
+            p_state_current->i_x = i_x;
+            p_state_current->i_y = i_y;
+
             if( p_state_prev )
                 p_state_prev->p_next = p_state_current;
             else
                 p_current->p_states = p_state_current;
             p_state_current->p_prev = p_state_prev;
 
-            msg_Dbg( p_this, " |- state=%s, file=%s%s", &state[0], (*p_menu)->psz_path, &file[0] );
+            msg_Dbg( p_this, " |- state=%s, file=%s%s", &state[0],
+                     p_menu->psz_path, &file[0] );
         }
         p_current->p_current_state = p_current->p_states;
     }
@@ -438,21 +497,21 @@ int E_(osd_parser_simpleOpen) ( vlc_object_t *p_this )
     /* Find the last button and store its pointer.
      * The OSD menu behaves like a roundrobin list.
      */
-    p_current = (*p_menu)->p_button;
+    p_current = p_menu->p_button;
     while( p_current && p_current->p_next )
     {
         osd_button_t *p_temp = NULL;
         p_temp = p_current->p_next;
         p_current = p_temp;
     }
-    (*p_menu)->p_last_button = p_current;
+    p_menu->p_last_button = p_current;
     fclose( fd );
     return VLC_SUCCESS;
 
-#undef MAX_FILE_PATH
 error:
-    msg_Err( p_this, "parsing file failed (returned %d)", result );
-    osd_MenuFree( p_this, *p_menu );
+    msg_Err( p_menu, "parsing file failed (returned %d)", result );
+    if( p_menu )
+        osd_MenuFree( p_menu );
     fclose( fd );
     return VLC_EGENERIC;
 }