[llvm] [Support] Preserve tilde paths when home lookup fails (PR #209479)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 06:34:16 PDT 2026


https://github.com/NotPppp1116 created https://github.com/llvm/llvm-project/pull/209479

## What

- preserve a normalized `~` path when the home-directory lookup fails
- treat an empty `HOME` value as unavailable and fall back to the password database on Unix
- add coverage for the empty-`HOME` fallback

## Why

`path::native` unconditionally replaced a tilde-prefixed path with the home lookup output. If that lookup failed, `~/file` became `/file`. An empty `HOME` was also accepted as a successful lookup, producing the same incorrect expansion even when the password database contained a valid home directory.

## Impact

Failed expansion leaves the normalized tilde path intact, while an empty Unix `HOME` now uses the existing password-database fallback.

## Checks

- built `SupportTests`
- `Support.HomeDirectory*`: 3/3 passed


>From 2d1bd4dc12afdee967787e4c3ca6f300cddafec1 Mon Sep 17 00:00:00 2001
From: Pppp1116 <ACCOUNT1_NOREPLY>
Date: Tue, 14 Jul 2026 14:23:17 +0100
Subject: [PATCH] [Support] Preserve tilde paths when home lookup fails

---
 llvm/lib/Support/Path.cpp       |  7 ++++---
 llvm/lib/Support/Unix/Path.inc  |  2 +-
 llvm/unittests/Support/Path.cpp | 14 ++++++++++++++
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 65e294020291f..e4b505653b1de 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -573,9 +573,10 @@ void native(SmallVectorImpl<char> &Path, Style style) {
         Ch = preferred_separator(style);
     if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) {
       SmallString<128> PathHome;
-      home_directory(PathHome);
-      PathHome.append(Path.begin() + 1, Path.end());
-      Path = std::move(PathHome);
+      if (home_directory(PathHome)) {
+        PathHome.append(Path.begin() + 1, Path.end());
+        Path = std::move(PathHome);
+      }
     }
   } else {
     llvm::replace(Path, '\\', '/');
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index f5b01357565df..bd897c27344da 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -1493,7 +1493,7 @@ namespace path {
 bool home_directory(SmallVectorImpl<char> &result) {
   std::unique_ptr<char[]> Buf;
   char *RequestedDir = getenv("HOME");
-  if (!RequestedDir) {
+  if (!RequestedDir || !*RequestedDir) {
     long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
     if (BufSize <= 0)
       BufSize = 16384;
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index b63ab426bb080..1234345eb7c5b 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -513,6 +513,20 @@ TEST(Support, HomeDirectoryWithNoEnv) {
   EXPECT_EQ(PwDir, HomeDir);
 }
 
+TEST(Support, HomeDirectoryWithEmptyEnv) {
+  WithEnv Env("HOME", "");
+
+  // Don't run the test if we have nothing to compare against.
+  struct passwd *pw = getpwuid(getuid());
+  if (!pw || !pw->pw_dir)
+    GTEST_SKIP();
+  std::string PwDir = pw->pw_dir;
+
+  SmallString<128> HomeDir;
+  EXPECT_TRUE(path::home_directory(HomeDir));
+  EXPECT_EQ(PwDir, HomeDir);
+}
+
 TEST(Support, ConfigDirectoryWithEnv) {
   WithEnv Env("XDG_CONFIG_HOME", "/xdg/config");
 



More information about the llvm-commits mailing list