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

New VLM quoting and escaping logic that is more like the usual C one[1]

- Do not validate quotes recursively (there is no reason to do that)
  and it is really unlike anything else.
- Do not allow escaping non-ASCII (to avoid UTF-8 breakages)
  or non-printable characters.
[1] we don't support every features of C escaping though
parent d3cd1b4d
......@@ -253,89 +253,88 @@ int vlm_Load( vlm_t *p_vlm, const char *psz_file )
return 0;
}
/*****************************************************************************
* FindEndCommand
*****************************************************************************/
static const char *FindEndCommand( const char *psz_sent )
/**
* FindCommandEnd: look for the end of a possibly quoted string
* @return NULL on mal-formatted string,
* pointer paste the last character otherwise.
*/
static const char *FindCommandEnd (const char *psz_sent)
{
vlc_bool_t b_escape = VLC_FALSE;
char quote = psz_sent[0], c;
static const char quotes[] = "'\"";
switch( *psz_sent )
{
case '\"':
psz_sent++;
while( ( *psz_sent != '\"' || b_escape == VLC_TRUE )
&& ( *psz_sent != '\0' ) )
if (quote && (strchr (quotes, quote) == NULL))
quote = '\0';
while ((c = *psz_sent) != '\0')
{
if( *psz_sent == '\'' && b_escape == VLC_FALSE )
if (c == '\\')
{
psz_sent = FindEndCommand( psz_sent );
if( psz_sent == NULL ) return NULL;
if (*psz_sent == '\0')
return NULL; // cannot escape "nothing"
psz_sent++; // skips escaped character
}
else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
b_escape = VLC_TRUE;
else
b_escape = VLC_FALSE;
}
if (c == quote) // non-escaped matching quote
return psz_sent + 1;
else
if (isblank (c)) // non-escaped blank
return psz_sent;
if( *psz_sent == '\"' )
{
psz_sent++;
return psz_sent;
}
/* *psz_sent == '\0' -> number of " is incorrect */
else return NULL;
// error (NULL) if we could not find a matching quote
return quote ? NULL : psz_sent;
}
break;
case '\'':
psz_sent++;
while( ( *psz_sent != '\'' || b_escape == VLC_TRUE )
&& ( *psz_sent != '\0' ) )
/**
* Unescape (C-style) a nul-terminated string.
* Note that in and out can be identical.
*
* @param out output buffer (at least <strlen (in) + 1> characters long)
* @param in nul-terminated string to be unescaped
*
* @return 0 on success, -1 on error.
*/
static int Unescape (char *out, const char *in)
{
char c;
while ((c = *in++) != '\0')
{
if( *psz_sent == '\"' && b_escape == VLC_FALSE )
if (c == '\\')
{
psz_sent = FindEndCommand( psz_sent );
if( psz_sent == NULL ) return NULL;
}
else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
b_escape = VLC_TRUE;
else
b_escape = VLC_FALSE;
}
if( *psz_sent == '\'' )
switch (c = *in++)
{
psz_sent++;
return psz_sent;
}
/* *psz_sent == '\0' -> number of " is incorrect */
else return NULL;
case 'n':
*out++ = '\n';
continue;
break;
case 't':
*out++ = '\t';
continue;
default: /* now we can look for spaces */
while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
{
if( ( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
&& b_escape == VLC_FALSE )
{
psz_sent = FindEndCommand( psz_sent );
if( psz_sent == NULL ) return NULL;
case 'r':
*out++ = '\r';
continue;
}
else if( *psz_sent++ == '\\' && b_escape == VLC_FALSE )
b_escape = VLC_TRUE;
else
b_escape = VLC_FALSE;
// Only allow printable ASCII characters
// (in particular, no nul and no extended characters)
if (c < 32)
return -1;
}
return psz_sent;
*out++ = c;
}
*out = '\0';
return 0;
}
/*****************************************************************************
* ExecuteCommand: The main state machine
*****************************************************************************
......@@ -353,7 +352,6 @@ static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
/* First, parse the line and cut it */
while( *psz_cmd != '\0' )
{
if( *psz_cmd == ' ' || *psz_cmd == '\t' )
{
psz_cmd++;
......@@ -361,10 +359,6 @@ static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
else
{
const char *psz_temp;
const char *psz_buf;
char *psz_dst;
vlc_bool_t b_escape = VLC_FALSE;
int i_temp;
/* support for comments */
if( i_command == 0 && *psz_cmd == '#')
......@@ -373,7 +367,7 @@ static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
goto success;
}
psz_temp = FindEndCommand( psz_cmd );
psz_temp = FindCommandEnd( psz_cmd );
if( psz_temp == NULL )
{
......@@ -381,31 +375,14 @@ static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
goto error;
}
i_temp = psz_temp - psz_cmd;
ppsz_command = realloc( ppsz_command, (i_command + 1) *
sizeof(char*) );
ppsz_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
ppsz_command[i_command] = strndup (psz_cmd, psz_temp - psz_cmd);
/* unescape ", ' and \ ... and everything else */
psz_buf = psz_cmd;
psz_dst = ppsz_command[ i_command ];
while( i_temp-- )
{
if( *psz_buf == '\\' && b_escape == VLC_FALSE )
b_escape = VLC_TRUE;
else
{
b_escape = VLC_FALSE;
*psz_dst = *psz_buf;
psz_dst++;
}
psz_buf++;
}
*psz_dst = '\0';
Unescape (ppsz_command[i_command], ppsz_command[i_command]);
i_command++;
psz_cmd = psz_temp;
}
}
......
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