@@ -2,6 +2,8 @@ use crate::error::{Result, SofosError};
22use std:: path:: PathBuf ;
33use std:: process:: Command ;
44
5+ const MAX_OUTPUT_SIZE : usize = 10 * 1024 * 1024 ; // 10MB limit
6+
57pub struct BashExecutor {
68 workspace : PathBuf ,
79}
@@ -25,6 +27,22 @@ impl BashExecutor {
2527 . output ( )
2628 . map_err ( |e| SofosError :: ToolExecution ( format ! ( "Failed to execute command: {}" , e) ) ) ?;
2729
30+ if output. stdout . len ( ) > MAX_OUTPUT_SIZE {
31+ return Err ( SofosError :: ToolExecution ( format ! (
32+ "Command output too large ({} bytes). Maximum size is {} MB" ,
33+ output. stdout. len( ) ,
34+ MAX_OUTPUT_SIZE / ( 1024 * 1024 )
35+ ) ) ) ;
36+ }
37+
38+ if output. stderr . len ( ) > MAX_OUTPUT_SIZE {
39+ return Err ( SofosError :: ToolExecution ( format ! (
40+ "Command error output too large ({} bytes). Maximum size is {} MB" ,
41+ output. stderr. len( ) ,
42+ MAX_OUTPUT_SIZE / ( 1024 * 1024 )
43+ ) ) ) ;
44+ }
45+
2846 let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
2947 let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
3048
@@ -207,4 +225,22 @@ mod tests {
207225 assert ! ( !executor. is_safe_command( "popd" ) ) ;
208226 assert ! ( !executor. is_safe_command( "ls && pushd .." ) ) ;
209227 }
228+
229+ #[ test]
230+ fn test_output_size_limit ( ) {
231+ use tempfile;
232+
233+ let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
234+ let executor = BashExecutor :: new ( temp_dir. path ( ) . to_path_buf ( ) ) . unwrap ( ) ;
235+
236+ let result = executor. execute ( "seq 1 2000000" ) ;
237+
238+ assert ! ( result. is_err( ) ) ;
239+ if let Err ( SofosError :: ToolExecution ( msg) ) = result {
240+ assert ! ( msg. contains( "too large" ) ) ;
241+ assert ! ( msg. contains( "10 MB" ) ) ;
242+ } else {
243+ panic ! ( "Expected ToolExecution error" ) ;
244+ }
245+ }
210246}
0 commit comments