@@ -329,6 +329,7 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
329329{
330330 std::filesystem::path tmpDir = nix::createTempDir ();
331331 nix::AutoDelete delTmpDir (tmpDir, /* recursive=*/ true );
332+ using namespace nix ::unix;
332333
333334 {
334335 RestoreSink sink (/* startFsync=*/ false );
@@ -341,12 +342,19 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
341342 sink.createSymlink (CanonPath (" a/absolute_symlink" ), tmpDir.string ());
342343 sink.createSymlink (CanonPath (" a/relative_symlink" ), " ../." );
343344 sink.createSymlink (CanonPath (" a/broken_symlink" ), " ./nonexistent" );
345+ sink.createDirectory (CanonPath (" a/b" ), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {
346+ dirSink.createDirectory (CanonPath (" d" ));
347+ dirSink.createSymlink (CanonPath (" c" ), " ./d" );
348+ });
349+ sink.createDirectory (CanonPath (" a/b/c/e" )); // FIXME: This still follows symlinks
350+ ASSERT_THROW (
351+ sink.createDirectory (
352+ CanonPath (" a/b/c/f" ), [](FileSystemObjectSink & dirSink, const CanonPath & relPath) {}),
353+ SymlinkNotAllowed);
344354 }
345355
346356 AutoCloseFD dirFd = openDirectory (tmpDir);
347357
348- using namespace nix ::unix;
349-
350358 auto open = [&](std::string_view path, int flags, mode_t mode = 0 ) {
351359 return openFileEnsureBeneathNoSymlinks (dirFd.get (), CanonPath (path), flags, mode);
352360 };
@@ -356,6 +364,7 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
356364 EXPECT_THROW (open (" a/absolute_symlink/a" , O_RDONLY), SymlinkNotAllowed);
357365 EXPECT_THROW (open (" a/absolute_symlink/c/d" , O_RDONLY), SymlinkNotAllowed);
358366 EXPECT_THROW (open (" a/relative_symlink/c" , O_RDONLY), SymlinkNotAllowed);
367+ EXPECT_THROW (open (" a/b/c/d" , O_RDONLY), SymlinkNotAllowed);
359368 EXPECT_EQ (open (" a/broken_symlink" , O_CREAT | O_WRONLY | O_EXCL, 0666 ), INVALID_DESCRIPTOR);
360369 /* Sanity check, no symlink shenanigans and behaves the same as regular openat with O_EXCL | O_CREAT. */
361370 EXPECT_EQ (errno, EEXIST);
0 commit comments