Add some input validation code to various functions

darcs-hash:20060222154152-ac50b-608032284165f099beecd1cd4f7c6bb2b45df432.gz
This commit is contained in:
axel 2006-02-23 01:41:52 +10:00
parent 3afead1827
commit ca04fc745d
11 changed files with 225 additions and 84 deletions

View file

@ -212,8 +212,13 @@ wchar_t *str2wcs( const char *in )
size_t len = strlen(in); size_t len = strlen(in);
out = malloc( sizeof(wchar_t)*(len+1) ); out = malloc( sizeof(wchar_t)*(len+1) );
if( !out )
{
die_mem();
}
return str2wcs_internal( in, out ); return str2wcs_internal( in, out );
} }
wchar_t *str2wcs_internal( const char *in, wchar_t *out ) wchar_t *str2wcs_internal( const char *in, wchar_t *out )
@ -226,11 +231,6 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
memset( &state, 0, sizeof(state) ); memset( &state, 0, sizeof(state) );
if( !out )
{
die_mem();
}
while( in[in_pos] ) while( in[in_pos] )
{ {
res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state ); res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );

View file

@ -481,8 +481,10 @@ void complete_remove( const wchar_t *cmd,
{ {
wchar_t *pos2 = pos+1; wchar_t *pos2 = pos+1;
while( *pos2 == L':' ) while( *pos2 == L':' )
{
pos2++; pos2++;
}
memmove( pos, memmove( pos,
pos2, pos2,
sizeof(wchar_t)*wcslen(pos2) ); sizeof(wchar_t)*wcslen(pos2) );
@ -500,7 +502,9 @@ void complete_remove( const wchar_t *cmd,
free( o ); free( o );
} }
else else
{
oprev = o; oprev = o;
}
} }
} }
@ -523,7 +527,9 @@ void complete_remove( const wchar_t *cmd,
} }
if( e ) if( e )
{
eprev = e; eprev = e;
}
} }
} }
@ -541,8 +547,14 @@ static void parse_cmd_string( const wchar_t *str,
/* Get the path of the command */ /* Get the path of the command */
path = get_filename( str ); path = get_filename( str );
if( path == 0 ) if( path == 0 )
{
/**
Use the empty string as the 'path' for commands that can
not be found.
*/
path = wcsdup(L""); path = wcsdup(L"");
}
/* Make sure the path is not included in the command */ /* Make sure the path is not included in the command */
cmd = wcsrchr( str, L'/' ); cmd = wcsrchr( str, L'/' );
if( cmd != 0 ) if( cmd != 0 )
@ -611,11 +623,11 @@ int complete_is_valid_option( const wchar_t *str,
return 0; return 0;
} }
if( !(short_validated = malloc( wcslen( opt ) ))) if( !(short_validated = malloc( wcslen( opt ) )))
{
die_mem(); die_mem();
}
memset( short_validated, 0, wcslen( opt ) ); memset( short_validated, 0, wcslen( opt ) );
hash_init( &gnu_match_hash, hash_init( &gnu_match_hash,
@ -649,8 +661,10 @@ int complete_is_valid_option( const wchar_t *str,
const wchar_t *a; const wchar_t *a;
if( !wildcard_match( match, i->cmd ) ) if( !wildcard_match( match, i->cmd ) )
{
continue; continue;
}
found_match = 1; found_match = 1;
if( !i->authorative ) if( !i->authorative )
@ -666,15 +680,19 @@ int complete_is_valid_option( const wchar_t *str,
for( o = i->first_option; o; o=o->next ) for( o = i->first_option; o; o=o->next )
{ {
if( o->old_mode ) if( o->old_mode )
{
continue; continue;
}
if( wcsncmp( &opt[2], o->long_opt, gnu_opt_len )==0) if( wcsncmp( &opt[2], o->long_opt, gnu_opt_len )==0)
{ {
hash_put( &gnu_match_hash, o->long_opt, L"" ); hash_put( &gnu_match_hash, o->long_opt, L"" );
if( (wcsncmp( &opt[2], if( (wcsncmp( &opt[2],
o->long_opt, o->long_opt,
wcslen( o->long_opt) )==0) ) wcslen( o->long_opt) )==0) )
{
is_gnu_exact=1; is_gnu_exact=1;
}
} }
} }
} }
@ -926,24 +944,30 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
switch( errno ) switch( errno )
{ {
case ENOENT: case ENOENT:
{
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_ROTTEN_SYMLINK_DESC ); sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_ROTTEN_SYMLINK_DESC );
break; break;
}
case EACCES: case EACCES:
{
break; break;
}
default: default:
{
if( errno == ELOOP ) if( errno == ELOOP )
{ {
sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_LOOP_SYMLINK_DESC ); sb_printf( get_desc_buff, L"%lc%ls", COMPLETE_SEP, COMPLETE_LOOP_SYMLINK_DESC );
} }
/* /*
Some kind of broken symlink. We ignore it Some kind of unknown broken symlink. We
here, and it will get a 'file' description, ignore it here, and it will get a 'file'
or one based on suffix. description, or one based on suffix.
*/ */
break; break;
}
} }
} }
@ -1013,19 +1037,14 @@ static void copy_strings_with_prefix( array_list_t *comp_out,
if(!tmp) if(!tmp)
return; return;
if( tmp[0] == L'~' )
{
tmp=expand_tilde(wc);
}
wc = parse_util_unescape_wildcards( tmp ); wc = parse_util_unescape_wildcards( tmp );
free(tmp); free(tmp);
for( i=0; i<al_get_count( possible_comp ); i++ ) for( i=0; i<al_get_count( possible_comp ); i++ )
{ {
wchar_t *next_str = (wchar_t *)al_get( possible_comp, i ); wchar_t *next_str = (wchar_t *)al_get( possible_comp, i );
if( next_str )
wildcard_complete( next_str, wc, desc, desc_func, comp_out ); wildcard_complete( next_str, wc, desc, desc_func, comp_out );
} }
free( wc ); free( wc );
@ -1358,10 +1377,26 @@ static void complete_from_args( const wchar_t *str,
for( i=0; i< al_get_count( &possible_comp ); i++ ) for( i=0; i< al_get_count( &possible_comp ); i++ )
{ {
wchar_t *next = (wchar_t *)al_get( &possible_comp, i ); wchar_t *next = (wchar_t *)al_get( &possible_comp, i );
al_set( &possible_comp , i, unescape( next, 0 ) ); wchar_t *next_unescaped;
free( next ); if( next )
{
next_unescaped = unescape( next, 0 );
if( next_unescaped )
{
al_set( &possible_comp , i, next_unescaped );
}
else
{
debug( 2, L"Could not expand string %ls on line %d of file %s", next, __LINE__, __FILE__ );
}
free( next );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
} }
copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp ); copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp );
al_foreach( &possible_comp, (void (*)(const void *))&free ); al_foreach( &possible_comp, (void (*)(const void *))&free );
@ -1674,11 +1709,11 @@ static void complete_param_expand( wchar_t *str,
comp_str = str; comp_str = str;
} }
debug( 2, debug( 3,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );", L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str, comp_str,
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" ); do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
expand_string( 0, expand_string( 0,
wcsdup(comp_str), wcsdup(comp_str),
comp_out, comp_out,
@ -1753,10 +1788,8 @@ static int try_complete_variable( const wchar_t *cmd,
{ {
return 0; return 0;
} }
} }
return 0; return 0;
} }
/** /**

View file

@ -214,7 +214,7 @@ void env_universal_init( wchar_t * p,
void (*sf)(), void (*sf)(),
void (*cb)( int type, const wchar_t *name, const wchar_t *val )) void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
{ {
debug( 2, L"env_universal_init()" ); debug( 3, L"env_universal_init()" );
path=p; path=p;
user=u; user=u;
start_fishd=sf; start_fishd=sf;
@ -233,7 +233,7 @@ void env_universal_init( wchar_t * p,
{ {
env_universal_barrier(); env_universal_barrier();
} }
debug( 2, L"end env_universal_init()" ); debug( 3, L"end env_universal_init()" );
} }
void env_universal_destroy() void env_universal_destroy()

View file

@ -105,7 +105,7 @@ static int get_names_show_unexported;
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) ) void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
{ {
debug( 2, L"Init env_universal_common" ); debug( 3, L"Init env_universal_common" );
callback = cb; callback = cb;
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp ); hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
} }
@ -229,7 +229,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
static void parse_message( wchar_t *msg, static void parse_message( wchar_t *msg,
connection_t *src ) connection_t *src )
{ {
debug( 2, L"parse_message( %ls );", msg ); debug( 3, L"parse_message( %ls );", msg );
if( msg[0] == L'#' ) if( msg[0] == L'#' )
return; return;

17
exec.c
View file

@ -1260,10 +1260,16 @@ int exec_subshell( const wchar_t *cmd,
{ {
wchar_t *el = str2wcs( begin ); wchar_t *el = str2wcs( begin );
if( el ) if( el )
{
al_push( l, el ); al_push( l, el );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
} }
io_buffer_destroy( io_buffer ); io_buffer_destroy( io_buffer );
return status; return status;
case '\n': case '\n':
@ -1271,7 +1277,14 @@ int exec_subshell( const wchar_t *cmd,
wchar_t *el; wchar_t *el;
*end=0; *end=0;
el = str2wcs( begin ); el = str2wcs( begin );
al_push( l, el ); if( el )
{
al_push( l, el );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
begin = end+1; begin = end+1;
break; break;
} }

View file

@ -1189,6 +1189,18 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
int i, j; int i, j;
const wchar_t *item_begin; const wchar_t *item_begin;
if( !in )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( !out )
{
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
switch( parse_util_locate_cmdsubst(in, switch( parse_util_locate_cmdsubst(in,
&paran_begin, &paran_begin,
&paran_end, &paran_end,
@ -1205,7 +1217,6 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
case 1: case 1:
break; break;
} }
len1 = (paran_begin-in); len1 = (paran_begin-in);
@ -1254,10 +1265,10 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
sb_append_substring( &whole_item, sub_item2, item_len ); sb_append_substring( &whole_item, sub_item2, item_len );
sb_append_char( &whole_item, INTERNAL_SEPARATOR ); sb_append_char( &whole_item, INTERNAL_SEPARATOR );
sb_append( &whole_item, tail_item ); sb_append( &whole_item, tail_item );
al_push( out, whole_item.buff ); al_push( out, whole_item.buff );
} }
free( sub_item2 ); free( sub_item2 );
} }
free(in); free(in);
@ -1438,23 +1449,18 @@ int expand_string( void *context,
if( EXPAND_SKIP_SUBSHELL & flags ) if( EXPAND_SKIP_SUBSHELL & flags )
{ {
wchar_t *pos = str; const wchar_t *begin, *end;
while( 1 ) if( parse_util_locate_cmdsubst( str,
&begin,
&end,
1 ) != 0 )
{ {
pos = wcschr( pos, L'(' ); error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
if( pos == 0 ) free( str );
break; al_destroy( &list1 );
al_destroy( &list2 );
if( (pos == str) || ( *(pos-1) != L'\\' ) ) return EXPAND_ERROR;
{
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
return EXPAND_ERROR;
}
pos++;
} }
al_push( &list1, str ); al_push( &list1, str );
} }
@ -1483,7 +1489,10 @@ int expand_string( void *context,
free( (void *)al_get( in, i ) ); free( (void *)al_get( in, i ) );
if( !next ) if( !next )
continue; {
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( EXPAND_SKIP_VARIABLES & flags ) if( EXPAND_SKIP_VARIABLES & flags )
{ {
@ -1492,7 +1501,6 @@ int expand_string( void *context,
if( *tmp == VARIABLE_EXPAND ) if( *tmp == VARIABLE_EXPAND )
*tmp = L'$'; *tmp = L'$';
al_push( out, next ); al_push( out, next );
} }
else else
{ {
@ -1513,6 +1521,13 @@ int expand_string( void *context,
for( i=0; i<al_get_count( in ); i++ ) for( i=0; i<al_get_count( in ); i++ )
{ {
wchar_t *next = (wchar_t *)al_get( in, i ); wchar_t *next = (wchar_t *)al_get( in, i );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( !expand_brackets( next, flags, out )) if( !expand_brackets( next, flags, out ))
{ {
al_destroy( in ); al_destroy( in );
@ -1528,6 +1543,13 @@ int expand_string( void *context,
for( i=0; i<al_get_count( in ); i++ ) for( i=0; i<al_get_count( in ); i++ )
{ {
wchar_t *next = (wchar_t *)al_get( in, i ); wchar_t *next = (wchar_t *)al_get( in, i );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( !(next=expand_tilde_internal( next ) ) ) if( !(next=expand_tilde_internal( next ) ) )
{ {
al_destroy( in ); al_destroy( in );
@ -1572,6 +1594,12 @@ int expand_string( void *context,
wchar_t *next = (wchar_t *)al_get( in, i ); wchar_t *next = (wchar_t *)al_get( in, i );
int wc_res; int wc_res;
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags ); remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) || if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
@ -1590,27 +1618,46 @@ int expand_string( void *context,
switch( wc_res ) switch( wc_res )
{ {
case 0: case 0:
{
if( !(flags & ACCEPT_INCOMPLETE) ) if( !(flags & ACCEPT_INCOMPLETE) )
{ {
if( res == EXPAND_OK ) if( res == EXPAND_OK )
res = EXPAND_WILDCARD_NO_MATCH; res = EXPAND_WILDCARD_NO_MATCH;
break; break;
} }
}
case 1: case 1:
{
int j;
res = EXPAND_WILDCARD_MATCH; res = EXPAND_WILDCARD_MATCH;
sort_list( out ); sort_list( out );
al_push_all( end_out, out );
for( j=0; j<al_get_count( out ); j++ )
{
wchar_t *next = (wchar_t *)al_get( out, j );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
al_push( end_out, next );
}
al_truncate( out, 0 ); al_truncate( out, 0 );
break; break;
}
} }
} }
else else
{ {
if( flags & ACCEPT_INCOMPLETE) if( flags & ACCEPT_INCOMPLETE)
{
free( next ); free( next );
}
else else
{
al_push( end_out, next ); al_push( end_out, next );
}
} }
} }
al_destroy( in ); al_destroy( in );

26
main.c
View file

@ -122,6 +122,10 @@ int main( int argc, char **argv )
"command", required_argument, 0, 'c' "command", required_argument, 0, 'c'
} }
, ,
{
"debug-level", required_argument, 0, 'd'
}
,
{ {
"interactive", no_argument, 0, 'i' "interactive", no_argument, 0, 'i'
} }
@ -152,14 +156,14 @@ int main( int argc, char **argv )
int opt = getopt_long( argc, int opt = getopt_long( argc,
argv, argv,
"hilvc:p:", "hilvc:p:d:",
long_options, long_options,
&opt_index ); &opt_index );
#else #else
int opt = getopt( argc, int opt = getopt( argc,
argv, argv,
"hilvc:p:" ); "hilvc:p:d:" );
#endif #endif
if( opt == -1 ) if( opt == -1 )
break; break;
@ -174,6 +178,22 @@ int main( int argc, char **argv )
is_interactive_session = 0; is_interactive_session = 0;
break; break;
case 'd':
{
char *end;
int tmp = strtol(optarg, &end, 10);
if( tmp >= 0 && tmp <=10 && !*end )
{
debug_level=tmp;
}
else
{
debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
exit(1);
}
break;
}
case 'h': case 'h':
cmd = "help"; cmd = "help";
break; break;
@ -233,7 +253,7 @@ int main( int argc, char **argv )
wchar_t *cmd_wcs = str2wcs( cmd ); wchar_t *cmd_wcs = str2wcs( cmd );
res = eval( cmd_wcs, 0, TOP ); res = eval( cmd_wcs, 0, TOP );
free(cmd_wcs); free(cmd_wcs);
reader_exit(0); reader_exit(0);
} }
else else
{ {

View file

@ -155,16 +155,12 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
return 0; return 0;
} }
*begin = paran_begin; if( begin )
*end = paran_count?in+wcslen(in):paran_end; *begin = paran_begin;
if( end )
*end = paran_count?in+wcslen(in):paran_end;
/* assert( *begin >= in );
assert( *begin < (in+wcslen(in) ) );
assert( *end >= *begin );
assert( *end < (in+wcslen(in) ) );
*/
return 1; return 1;
} }

View file

@ -708,7 +708,7 @@ wchar_t *get_filename( const wchar_t *cmd )
{ {
wchar_t *path; wchar_t *path;
debug( 2, L"get_filename( '%ls' )", cmd ); debug( 3, L"get_filename( '%ls' )", cmd );
if(wcschr( cmd, L'/' ) != 0 ) if(wcschr( cmd, L'/' ) != 0 )
{ {
@ -948,7 +948,14 @@ int eval_args( const wchar_t *line, array_list_t *args )
{ {
case TOK_STRING: case TOK_STRING:
{ {
if( expand_string( 0, wcsdup(tok_last( &tok )), args, 0 ) == EXPAND_ERROR ) wchar_t *tmp = wcsdup(tok_last( &tok ));
if( !tmp )
{
die_mem();
}
if( expand_string( 0, tmp, args, 0 ) == EXPAND_ERROR )
{ {
err_pos=tok_get_pos( &tok ); err_pos=tok_get_pos( &tok );
do_loop=0; do_loop=0;

View file

@ -567,11 +567,12 @@ static void remove_duplicates( array_list_t *l )
prev = (wchar_t *)al_get( l, 0 ); prev = (wchar_t *)al_get( l, 0 );
for( in=1, out=1; in < al_get_count( l ); in++ ) for( in=1, out=1; in < al_get_count( l ); in++ )
{ {
wchar_t *curr = (wchar_t *)al_get( l, in ); wchar_t *curr = (wchar_t *)al_get( l, in );
if( fldcmp( prev, curr )==0 ) if( fldcmp( prev, curr )==0 )
{ {
free( curr ); free( curr );
} }
else else
{ {
@ -2036,7 +2037,6 @@ void reader_set_buffer( wchar_t *b, int p )
else else
{ {
data->buff_pos=l; data->buff_pos=l;
// fwprintf( stderr, L"Pos %d\n", l );
} }
reader_super_highlight_me_plenty( data->buff, reader_super_highlight_me_plenty( data->buff,

View file

@ -151,13 +151,32 @@ static int wildcard_complete_internal( const wchar_t *orig,
const wchar_t *(*desc_func)(const wchar_t *), const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out ) array_list_t *out )
{ {
if( !wc )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( !str )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( !orig )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( *wc == 0 && if( *wc == 0 &&
( ( *str != L'.') || (!is_first)) ) ( ( *str != L'.') || (!is_first)) )
{ {
if( !out )
return 1;
wchar_t *new; wchar_t *new;
if( !out )
{
return 1;
}
if( wcschr( str, PROG_COMPLETE_SEP ) ) if( wcschr( str, PROG_COMPLETE_SEP ) )
{ {
@ -165,7 +184,7 @@ static int wildcard_complete_internal( const wchar_t *orig,
This completion has an embedded description, du not use the generic description This completion has an embedded description, du not use the generic description
*/ */
wchar_t *sep; wchar_t *sep;
new = wcsdup( str ); new = wcsdup( str );
sep = wcschr(new, PROG_COMPLETE_SEP ); sep = wcschr(new, PROG_COMPLETE_SEP );
*sep = COMPLETE_SEP; *sep = COMPLETE_SEP;
@ -661,15 +680,19 @@ int wildcard_expand( const wchar_t *wc,
if( wc_end ) if( wc_end )
{ {
new_wc=wc_end+1; new_wc=wc_end+1;
/*
Accept multiple '/' as a single direcotry separator
*/
while(*new_wc==L'/') while(*new_wc==L'/')
{
new_wc++; new_wc++;
}
} }
res |= wildcard_expand( new_wc, res |= wildcard_expand( new_wc,
new_dir, new_dir,
flags, flags,
out ); out );
} }
/* /*
@ -694,8 +717,10 @@ int wildcard_expand( const wchar_t *wc,
closedir( dir ); closedir( dir );
if( flags & ACCEPT_INCOMPLETE ) if( flags & ACCEPT_INCOMPLETE )
{
sb_destroy( &sb_desc ); sb_destroy( &sb_desc );
}
return res; return res;
} }