@@ -1277,6 +1277,56 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje
12771277 }
12781278 }
12791279
1280+ @ Test
1281+ public void testCompositeFileSystemCreateSymbolicLinkRelativeTargetEscape () throws Exception {
1282+ Path tmp = Files .createTempDirectory ("truffle-file-test" );
1283+ try {
1284+ Path allowed = tmp .resolve ("allowed" ).toAbsolutePath ();
1285+ Files .createDirectories (allowed );
1286+ Path cwd = allowed .resolve ("cwd" ).toAbsolutePath ();
1287+ Files .createDirectories (cwd );
1288+ Path denied = tmp .resolve ("denied" ).toAbsolutePath ();
1289+ Files .writeString (denied , "denied" );
1290+
1291+ FileSystem noIO = FileSystem .newDenyIOFileSystem ();
1292+ FileSystem fullIO = FileSystem .newDefaultFileSystem ();
1293+ FileSystem .Selector fullIOPredicate = new FileSystem .Selector (fullIO ) {
1294+ @ Override
1295+ public boolean test (Path path ) {
1296+ return path .startsWith (allowed );
1297+ }
1298+ };
1299+ FileSystem compositeFs = FileSystem .newCompositeFileSystem (noIO , fullIOPredicate );
1300+ compositeFs .setCurrentWorkingDirectory (cwd );
1301+
1302+ IOAccess ioAccess = IOAccess .newBuilder ().fileSystem (compositeFs ).build ();
1303+ try (Context context = Context .newBuilder ().allowIO (ioAccess ).build ()) {
1304+ assertFails (
1305+ () -> AbstractExecutableTestLanguage .evalTestLanguage (
1306+ context , TestCompositeFileSystemCreateSymbolicLinkRelativeTargetEscape .class , "" , allowed .toString ()),
1307+ PolyglotException .class ,
1308+ (e ) -> Assert .assertTrue (e .getMessage ().contains ("Cross file system linking is not supported." )));
1309+ assertFalse (Files .exists (allowed .resolve ("link" )));
1310+ }
1311+ } finally {
1312+ delete (tmp );
1313+ }
1314+ }
1315+
1316+ @ Registration
1317+ static final class TestCompositeFileSystemCreateSymbolicLinkRelativeTargetEscape extends AbstractExecutableTestLanguage {
1318+
1319+ @ Override
1320+ @ TruffleBoundary
1321+ protected Object execute (RootNode node , Env env , Object [] contextArguments , Object [] frameArguments ) throws Exception {
1322+ TruffleFile allowed = env .getPublicTruffleFile ((String ) contextArguments [0 ]);
1323+ TruffleFile link = allowed .resolve ("link" );
1324+ TruffleFile target = env .getPublicTruffleFile (".." ).resolve ("denied" );
1325+ link .createSymbolicLink (target );
1326+ return null ;
1327+ }
1328+ }
1329+
12801330 private static void delete (Path path ) throws IOException {
12811331 if (Files .isDirectory (path )) {
12821332 try (DirectoryStream <Path > dir = Files .newDirectoryStream (path )) {
0 commit comments