Serenity Operating System
at master 86 lines 3.1 kB view raw
1/* 2 * Copyright (c) 2021, Ben Wiederhake <BenWiederhake.GitHub@gmx.de> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibTest/TestCase.h> 8 9#include <AK/DeprecatedString.h> 10#include <AK/StringBuilder.h> 11#include <errno.h> 12#include <limits.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <sys/stat.h> 17#include <unistd.h> 18 19static constexpr char TMPDIR_PATTERN[] = "/tmp/overlong_realpath_XXXXXX"; 20static constexpr char PATH_LOREM_250[] = "This-is-an-annoyingly-long-name-that-should-take-up-exactly-two-hundred-and-fifty-characters-and-is-surprisingly-difficult-to-fill-with-reasonably-meaningful-text-which-is-necessary-because-that-makes-it-easier-for-my-eyes-to-spot-any-corruption-fast"; 21 22static constexpr size_t ITERATION_DEPTH = 17; 23 24static void check_result(char const* what, DeprecatedString const& expected, char const* actual) 25{ 26 if (expected != actual) 27 FAIL(DeprecatedString::formatted("Expected {} to be \"{}\" ({} characters)", what, actual, actual ? strlen(actual) : 0)); 28} 29 30TEST_CASE(overlong_realpath) 31{ 32 // We want to construct a path that is over PATH_MAX characters long. 33 // This cannot be done in a single step. 34 35 // First, switch to a known environment: 36 char tmp_dir[] = "/tmp/overlong_realpath_XXXXXX"; 37 38 errno = 0; 39 auto* new_dir = mkdtemp(tmp_dir); 40 VERIFY(new_dir != nullptr); 41 VERIFY(errno == 0); 42 43 errno = 0; 44 auto ret = chdir(tmp_dir); 45 VERIFY(ret >= 0); 46 VERIFY(errno == 0); 47 48 // Then, create a long path. 49 StringBuilder expected; 50 expected.append({ tmp_dir, strlen(tmp_dir) }); 51 52 // But first, demonstrate the functionality at a reasonable depth: 53 auto expected_str = expected.to_deprecated_string(); 54 check_result("getwd", expected_str, getwd(static_cast<char*>(calloc(1, PATH_MAX)))); 55 check_result("getcwd", expected_str, getcwd(nullptr, 0)); 56 check_result("realpath", expected_str, realpath(".", nullptr)); 57 58 for (size_t i = 0; i < ITERATION_DEPTH; ++i) { 59 ret = mkdir(PATH_LOREM_250, S_IRWXU); 60 if (ret < 0) { 61 perror("mkdir iter"); 62 FAIL(DeprecatedString::formatted("Unable to mkdir the overlong path fragment in iteration {}", i)); 63 return; 64 } 65 expected.append('/'); 66 expected.append({ PATH_LOREM_250, strlen(PATH_LOREM_250) }); 67 ret = chdir(PATH_LOREM_250); 68 if (ret < 0) { 69 perror("chdir iter"); 70 FAIL(DeprecatedString::formatted("Unable to chdir to the overlong path fragment in iteration {}", i)); 71 return; 72 } 73 } 74 outln("cwd should now be ridiculously large"); 75 76 // Evaluate 77 expected_str = expected.to_deprecated_string(); 78 79 check_result("getwd", {}, getwd(static_cast<char*>(calloc(1, PATH_MAX)))); 80 check_result("getcwd", expected_str, getcwd(nullptr, 0)); 81 check_result("realpath", expected_str, realpath(".", nullptr)); 82 83 VERIFY(strlen(PATH_LOREM_250) == 250); 84 VERIFY(strlen(TMPDIR_PATTERN) + ITERATION_DEPTH * (1 + strlen(PATH_LOREM_250)) == expected_str.length()); 85 VERIFY(expected_str.length() > PATH_MAX); 86}