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