Boost logo

Boost-Commit :

From: grafikrobot_at_[hidden]
Date: 2007-11-27 12:58:50


Author: grafik
Date: 2007-11-27 12:58:50 EST (Tue, 27 Nov 2007)
New Revision: 41417
URL: http://svn.boost.org/trac/boost/changeset/41417

Log:
Fix buffer overrun bug in expanding @() subexpressions.
Text files modified:
   trunk/tools/jam/src/variable.c | 282 ++++++++++++++++++++-------------------
   1 files changed, 143 insertions(+), 139 deletions(-)

Modified: trunk/tools/jam/src/variable.c
==============================================================================
--- trunk/tools/jam/src/variable.c (original)
+++ trunk/tools/jam/src/variable.c 2007-11-27 12:58:50 EST (Tue, 27 Nov 2007)
@@ -177,143 +177,147 @@
 
 int
 var_string(
- char *in,
- char *out,
- int outsize,
- LOL *lol )
+ char *in,
+ char *out,
+ int outsize,
+ LOL *lol )
 {
- char *out0 = out;
- char *oute = out + outsize - 1;
+ char *out0 = out;
+ char *oute = out + outsize - 1;
 
- while( *in )
- {
- char *lastword;
- int dollar = 0;
+ while( *in )
+ {
+ char *lastword;
+ int dollar = 0;
 
- /* Copy white space */
+ /* Copy white space */
 
- while( isspace( *in ) )
- {
- if( out >= oute )
- return -1;
+ while( isspace( *in ) )
+ {
+ if( out >= oute )
+ return -1;
 
- *out++ = *in++;
- }
+ *out++ = *in++;
+ }
 
- lastword = out;
+ lastword = out;
 
- /* Copy non-white space, watching for variables */
+ /* Copy non-white space, watching for variables */
 
- while( *in && !isspace( *in ) )
- {
- if( out >= oute )
- return -1;
+ while( *in && !isspace( *in ) )
+ {
+ if( out >= oute )
+ return -1;
 
- if( in[0] == '$' && in[1] == '(' )
- dollar++;
- #ifdef OPT_AT_FILES
- else if ( in[0] == '@' && in[1] == '(' )
+ if( in[0] == '$' && in[1] == '(' )
+ {
+ dollar++;
+ *out++ = *in++;
+ }
+ #ifdef OPT_AT_FILES
+ else if ( in[0] == '@' && in[1] == '(' )
+ {
+ int depth = 1;
+ char *ine = in + 2;
+ char *split = 0;
+
+ /* Scan the content of the response file @() section. */
+
+ while( *ine && depth > 0 )
                 {
- int depth = 1;
- char *ine = in + 2;
- char *split = 0;
-
- /* Scan the content of the response file @() section. */
-
- while( *ine && depth > 0 )
+ switch( *ine )
                     {
- switch( *ine )
+ case '(':
+ ++depth;
+ break;
+ case ')':
+ --depth;
+ break;
+ case ':':
+ if( depth == 1 && ine[1] == 'E' && ine[2] == '=' )
                         {
- case '(':
- ++depth;
- break;
- case ')':
- --depth;
- break;
- case ':':
- if( depth == 1 && ine[1] == 'E' && ine[2] == '=' )
- {
- split = ine;
- }
- break;
+ split = ine;
                         }
- ++ine;
+ break;
                     }
+ ++ine;
+ }
+
+ if (!split)
+ {
+ /* the @() reference doesn't match the @(foo:E=bar) format.
+ hence we leave it alone by copying directly to output. */
+ int l = 0;
+ if ( out+2 >= oute ) return -1;
+ *(out++) = '@';
+ *(out++) = '(';
+ l = var_string(in+2,out,oute-out,lol);
+ if ( l < 0 ) return -1;
+ out += l;
+ if ( out+1 >= oute ) return -1;
+ *(out++) = ')';
+ }
+
+ else if ( depth == 0 )
+ {
+ string file_name_v;
+ int file_name_l = 0;
+ const char * file_name_s = 0;
                     
- if (!split)
- {
- /* the @() reference doesn't match the @(foo:E=bar) format.
- hence we leave it alone by copying directly to output. */
- int l = 0;
- if ( out+2 >= oute ) return -1;
- *(out++) = '@';
- *(out++) = '(';
- l = var_string(in+2,out,oute-out,lol);
- if ( l < 0 ) return -1;
- out += l;
- if ( out+1 >= oute ) return -1;
- *(out++) = ')';
- in = ine;
- }
+ /* expand the temporary file name var inline */
+ #if 0
+ string_copy(&file_name_v,"$(");
+ string_append_range(&file_name_v,in+2,split);
+ string_push_back(&file_name_v,')');
+ #else
+ string_new(&file_name_v);
+ string_append_range(&file_name_v,in+2,split);
+ #endif
+ file_name_l = var_string(file_name_v.value,out,oute-out+1,lol);
+ string_free(&file_name_v);
+ if ( file_name_l < 0 ) return -1;
+ file_name_s = out;
                     
- else if ( depth == 0 )
+ /* for stdout/stderr we will create a temp file and generate
+ a command that outputs the content as needed. */
+ if ( strcmp( "STDOUT", out ) == 0 || strcmp( "STDERR", out ) == 0 )
                     {
- string file_name_v;
- int file_name_l = 0;
- const char * file_name_s = 0;
-
- /* expand the temporary file name var inline */
- #if 0
- string_copy(&file_name_v,"$(");
- string_append_range(&file_name_v,in+2,split);
- string_push_back(&file_name_v,')');
+ int err_redir = strcmp( "STDERR", out ) == 0;
+ out[0] = '\0';
+ file_name_s = path_tmpfile();
+ file_name_l = strlen(file_name_s);
+ #ifdef OS_NT
+ if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1;
+ sprintf( out,"type \"%s\"%s",
+ file_name_s,
+ err_redir ? " 1>&2" : "" );
                         #else
- string_new(&file_name_v);
- string_append_range(&file_name_v,in+2,split);
+ if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1;
+ sprintf( out,"cat \"%s\"%s",
+ file_name_s,
+ err_redir ? " 1>&2" : "" );
                         #endif
- file_name_l = var_string(file_name_v.value,out,oute-out+1,lol);
- string_free(&file_name_v);
- if ( file_name_l < 0 ) return -1;
- file_name_s = out;
-
- /* for stdout/stderr we will create a temp file and generate
- a command that outputs the content as needed. */
- if ( strcmp( "STDOUT", out ) == 0 || strcmp( "STDERR", out ) == 0 )
- {
- int err_redir = strcmp( "STDERR", out ) == 0;
- out[0] = '\0';
- file_name_s = path_tmpfile();
- file_name_l = strlen(file_name_s);
- #ifdef OS_NT
- if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1;
- sprintf( out,"type \"%s\"%s",
- file_name_s,
- err_redir ? " 1>&2" : "" );
- #else
- if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1;
- sprintf( out,"cat \"%s\"%s",
- file_name_s,
- err_redir ? " 1>&2" : "" );
- #endif
- /* we also make sure that the temp files created by this
- get nuked eventually. */
- file_remove_atexit( file_name_s );
- }
-
- /* expand the file value into the file reference */
- var_string_to_file( split+3, ine-split-4, file_name_s, lol );
-
- /* continue on with the expansion */
- out += strlen(out);
+ /* we also make sure that the temp files created by this
+ get nuked eventually. */
+ file_remove_atexit( file_name_s );
                     }
                     
- /* and continue with the parsing just past the @() reference */
- in = ine;
+ /* expand the file value into the file reference */
+ var_string_to_file( split+3, ine-split-4, file_name_s, lol );
+
+ /* continue on with the expansion */
+ out += strlen(out);
                 }
- #endif
-
- *out++ = *in++;
- }
+
+ /* and continue with the parsing just past the @() reference */
+ in = ine;
+ }
+ #endif
+ else
+ {
+ *out++ = *in++;
+ }
+ }
 
         /* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
         if (out >= oute)
@@ -321,40 +325,40 @@
         /* Don't increment, intentionally. */
         *out= '\0';
            
- /* If a variable encountered, expand it and and embed the */
- /* space-separated members of the list in the output. */
+ /* If a variable encountered, expand it and and embed the */
+ /* space-separated members of the list in the output. */
 
- if( dollar )
- {
- LIST *l;
+ if( dollar )
+ {
+ LIST *l;
 
- l = var_expand( L0, lastword, out, lol, 0 );
+ l = var_expand( L0, lastword, out, lol, 0 );
 
- out = lastword;
+ out = lastword;
 
- while ( l )
- {
- int so = strlen( l->string );
+ while ( l )
+ {
+ int so = strlen( l->string );
 
- if( out + so >= oute )
- return -1;
+ if( out + so >= oute )
+ return -1;
 
- strcpy( out, l->string );
- out += so;
- l = list_next( l );
- if ( l ) *out++ = ' ';
- }
+ strcpy( out, l->string );
+ out += so;
+ l = list_next( l );
+ if ( l ) *out++ = ' ';
+ }
 
- list_free( l );
- }
- }
+ list_free( l );
+ }
+ }
 
- if( out >= oute )
- return -1;
+ if( out >= oute )
+ return -1;
 
- *out++ = '\0';
+ *out++ = '\0';
 
- return out - out0;
+ return out - out0;
 }
 
 void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk