From d6dd082adfb93716c31e5093b189fdedb64e5efe Mon Sep 17 00:00:00 2001 From: Mostyn Bramley-Moore Date: Mon, 7 Oct 2024 05:35:28 +0200 Subject: [PATCH] Add absolute path test for bsdtar (#2370) Check that extracting archive entries with absolute paths uses mangled relative paths unless -P / --absolute-paths is specified. --- Makefile.am | 1 + tar/test/CMakeLists.txt | 1 + tar/test/test_option_P.c | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 tar/test/test_option_P.c diff --git a/Makefile.am b/Makefile.am index 64af9afd9..53f47bb0c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1117,6 +1117,7 @@ bsdtar_test_SOURCES= \ tar/test/test_option_H_upper.c \ tar/test/test_option_L_upper.c \ tar/test/test_option_O_upper.c \ + tar/test/test_option_P.c \ tar/test/test_option_T_upper.c \ tar/test/test_option_U_upper.c \ tar/test/test_option_X_upper.c \ diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt index 7808a8d1f..09ad68015 100644 --- a/tar/test/CMakeLists.txt +++ b/tar/test/CMakeLists.txt @@ -32,6 +32,7 @@ IF(ENABLE_TAR AND ENABLE_TEST) test_option_H_upper.c test_option_L_upper.c test_option_O_upper.c + test_option_P.c test_option_T_upper.c test_option_U_upper.c test_option_X_upper.c diff --git a/tar/test/test_option_P.c b/tar/test/test_option_P.c new file mode 100644 index 000000000..e63da3e08 --- /dev/null +++ b/tar/test/test_option_P.c @@ -0,0 +1,82 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Mostyn Bramley-Moore + */ + +#include "test.h" + +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define UNLINK _unlink +#else +#define UNLINK unlink +#endif + +DEFINE_TEST(test_extract_tar_absolute_paths) +{ + int r; + + // Create an absolute path for a test file inside testworkdir. + char *entry_suffix = "/tar-noabs"; + size_t entry_suffix_length = strlen(entry_suffix); + size_t testworkdir_length = strlen(testworkdir); + size_t temp_absolute_file_name_length = testworkdir_length + entry_suffix_length; + char *temp_absolute_file_name = calloc(1, temp_absolute_file_name_length + 1); // +1 for null character. + assertEqualInt(snprintf(temp_absolute_file_name, temp_absolute_file_name_length + 1, "%s%s", testworkdir, entry_suffix), + temp_absolute_file_name_length); + +#if defined(_WIN32) && !defined(__CYGWIN__) + // I'm unsure how to specify paths with spaces for the test invocation on windows. + // Adding quotes doesn't seem to work. We should find a way to escape these paths, + // but for now let's fail in a place that's obviously related to the test setup if + // testworkdir contains spaces. + for (char *p = temp_absolute_file_name; *p != '\0'; p++) + { + assert(*p != ' '); + if (*p == ' ') break; + } +#endif + + // Create the file. + const char *sample_data = "test file from test_extract_tar_absolute_paths"; + assertMakeFile(temp_absolute_file_name, 0644, sample_data); + + // Create an archive with the test file, using an absolute path. +#if defined(_WIN32) && !defined(__CYGWIN__) + r = systemf("%s --absolute-paths -cf test.tar %s", testprog, temp_absolute_file_name); +#else + r = systemf("%s --absolute-paths -cf test.tar \"%s\"", testprog, temp_absolute_file_name); +#endif + assertEqualInt(r, 0); + + UNLINK(temp_absolute_file_name); + + // Extracting the archive without -P / --absolute-paths should strip leading drive letter or slash + r = systemf("%s -xf test.tar", testprog); + assertEqualInt(r, 0); + assertFileNotExists(temp_absolute_file_name); + + // Check that the mangled path exists. +#if defined(_WIN32) && !defined(__CYGWIN__) + assertFileExists(temp_absolute_file_name + 3); // Skip the drive letter, colon and slash. + UNLINK(temp_absolute_file_name + 3); +#else + assertFileExists(temp_absolute_file_name + 1); // Skip the slash. + UNLINK(temp_absolute_file_name + 1); +#endif + + // Extracting the archive with -P / --absolute-paths should create the file. + r = systemf("%s --absolute-paths -xf test.tar", testprog); + assertEqualInt(r, 0); + assertFileExists(temp_absolute_file_name); + + // Check that the mangled path wasn't created. +#if defined(_WIN32) && !defined(__CYGWIN__) + assertFileNotExists(temp_absolute_file_name + 3); // Skip the drive letter, colon and slash. +#else + assertFileNotExists(temp_absolute_file_name + 1); // Skip the slash. +#endif +} -- 2.47.2