[vlc-devel] [PATCH] input: var: fix #18332: multiple bookmark options leading to UB
Thomas Guillem
thomas at gllm.fr
Mon Jul 23 10:03:52 CEST 2018
Hi,
On Sat, Jul 21, 2018, at 21:57, Filip Roséen wrote:
> The crash was due to the previous imlpementation inaccurate
> assumptions regarding the input-data, more specifically it assumed
> that only one bookmarks= option would be present (something which is
> not guaranteed to be true).
>
> These changes also fixes a premature release of the input_item_t's
> mutex.
> ---
> src/input/var.c | 57 ++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 38 insertions(+), 19 deletions(-)
>
> diff --git a/src/input/var.c b/src/input/var.c
> index 9882b9e60a..43c50fd2e2 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -172,12 +172,13 @@ static const char *GetEsVarName( enum
> es_format_category_e i_cat )
> static void UpdateBookmarksOption( input_thread_t *p_input )
> {
> input_thread_private_t *priv = input_priv(p_input);
> + input_item_t* item = priv->p_item;
> struct vlc_memstream vstr;
>
> vlc_memstream_open( &vstr );
> vlc_memstream_puts( &vstr, "bookmarks=" );
>
> - vlc_mutex_lock( &priv->p_item->lock );
> + vlc_mutex_lock( &item->lock );
> var_Change( p_input, "bookmark", VLC_VAR_CLEARCHOICES );
>
> for( int i = 0; i < priv->i_bookmark; i++ )
> @@ -194,31 +195,49 @@ static void UpdateBookmarksOption( input_thread_t
> *p_input )
> i > 0 ? "," : "", sp->psz_name, ( 1. * sp-
> >i_time_offset ) / CLOCK_FREQ );
> }
>
> - vlc_mutex_unlock( &priv->p_item->lock );
> -
> - if( vlc_memstream_close( &vstr ) == VLC_SUCCESS )
> + if( vlc_memstream_close( &vstr ) )
> {
> - bool b_overwritten = false;
> + vlc_mutex_unlock( &item->lock );
> + return;
> + }
>
> - for( int i = 0; i < priv->p_item->i_options; ++i )
> - {
> - char** ppsz_option = &priv->p_item->ppsz_options[i];
> + /* XXX: The below is ugly and should be fixed elsewhere, but in order to
> + * not have more than one "bookmarks=" option associated with the item, we
> + * need to remove any existing ones before adding the new one. This logic
> + * should exist in input_item_AddOption with "OPTION_UNIQUE & <an overwrite
> + * flag>, but until then we handle it here. */
>
> - if( strncmp( *ppsz_option, "bookmarks=", 10 ) == 0 )
> - {
> - free( *ppsz_option );
> - *ppsz_option = vstr.ptr;
> - b_overwritten = true;
> - }
> - }
> + char** const orig_beg = &item->ppsz_options[0];
> + char** const orig_end = orig_beg + item->i_options;
> + char** end = orig_end;
>
> - if( !b_overwritten )
> + for( char** option = orig_beg; option != end; )
> + {
> + if( strncmp( *option, "bookmarks=", 10 ) )
> + ++option;
> + else
> {
> - input_item_AddOption( priv->p_item, vstr.ptr,
> - VLC_INPUT_OPTION_UNIQUE );
> - free( vstr.ptr );
> + free( *option );
> + /* It might be tempting to optimize the below by overwriting
> + * *option with the value of the last element, however; we want to
> + * preserve the order of the other options (as behavior might
> + * depend on it) */
> + memmove( option, option + 1, ( --end - option ) * sizeof *end );
> }
> }
> +
> + if( end != orig_end ) /* we removed at least 1 option */
> + {
> + *end = vstr.ptr;
> + item->i_options = end - orig_beg + 1;
> + vlc_mutex_unlock( &priv->p_item->lock );
> + }
> + else /* nothing removed, add the usual way */
> + {
> + vlc_mutex_unlock( &priv->p_item->lock );
> + input_item_AddOption( item, vstr.ptr, VLC_INPUT_OPTION_UNIQUE );
> + free( vstr.ptr );
> + }
> }
>
I would have created the VLC_INPUT_OPTION_OVERWRITE option. But since this function will disappear with the playlist (still planned for.0), we can keep this patch as is for now.
(OK for merging it)
> void input_LegacyEvents( input_thread_t *p_input, void *user_data,
> --
> 2.18.0
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list