@@ -879,6 +879,94 @@ fn clang_android() {
879879 }
880880}
881881
882+ #[ test]
883+ fn parent_dir_file_path ( ) {
884+ // Regression test for issue #172
885+ // https://github.com/rust-lang/cc-rs/issues/172
886+ // Ensures that files referenced with parent directory components (..)
887+ // have their object files placed within OUT_DIR, not in parent directories
888+
889+ reset_env ( ) ;
890+ let test = Test :: gnu ( ) ;
891+
892+ let intermediates = test
893+ . gcc ( )
894+ . file ( "../external_lib/test.c" )
895+ . compile_intermediates ( ) ;
896+
897+ // Verify we got an object file back
898+ assert_eq ! (
899+ intermediates. len( ) ,
900+ 1 ,
901+ "Expected exactly one intermediate object file"
902+ ) ;
903+
904+ let obj_path = & intermediates[ 0 ] ;
905+ let out_dir = test. td . path ( ) ;
906+
907+ // Verify the object file is actually within OUT_DIR
908+ assert ! (
909+ obj_path. starts_with( out_dir) ,
910+ "Object file {:?} is not within OUT_DIR {:?}. This indicates the file path \
911+ with parent directory components (..) caused the object file to escape OUT_DIR.",
912+ obj_path,
913+ out_dir
914+ ) ;
915+ }
916+
917+ #[ test]
918+ fn multiple_parent_dir_references ( ) {
919+ // Test deeply nested parent directory references
920+ // e.g., ../../deep/path/../file.c
921+
922+ reset_env ( ) ;
923+ let test = Test :: gnu ( ) ;
924+
925+ let intermediates = test
926+ . gcc ( )
927+ . file ( "a/b/c/../../b/c/deep.c" )
928+ . compile_intermediates ( ) ;
929+
930+ assert_eq ! ( intermediates. len( ) , 1 ) ;
931+ let obj_path = & intermediates[ 0 ] ;
932+ let out_dir = test. td . path ( ) ;
933+
934+ // Must be within OUT_DIR
935+ assert ! (
936+ obj_path. starts_with( out_dir) ,
937+ "Object file with multiple parent refs {:?} escaped OUT_DIR {:?}" ,
938+ obj_path,
939+ out_dir
940+ ) ;
941+ }
942+
943+ #[ test]
944+ fn parent_dir_with_multiple_files ( ) {
945+ // Test that multiple files with parent directory references
946+ // all get properly contained in OUT_DIR
947+
948+ reset_env ( ) ;
949+ let test = Test :: gnu ( ) ;
950+
951+ let intermediates = test
952+ . gcc ( )
953+ . file ( "src1/../src1/file1.c" )
954+ . file ( "src2/../src2/file2.c" )
955+ . compile_intermediates ( ) ;
956+
957+ assert_eq ! ( intermediates. len( ) , 2 , "Expected two object files" ) ;
958+
959+ let out_dir = test. td . path ( ) ;
960+ for obj_path in & intermediates {
961+ assert ! (
962+ obj_path. starts_with( out_dir) ,
963+ "Object file {:?} is not within OUT_DIR {:?}" ,
964+ obj_path,
965+ out_dir
966+ ) ;
967+ }
968+ }
969+
882970#[ cfg( windows) ]
883971#[ cfg( not( disable_clang_cl_tests) ) ]
884972mod msvc_clang_cl_tests {
0 commit comments