[llvm] llvm-ar: fix inconsistent case sensitivity for path matching on Windows (PR #196541)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 8 07:04:12 PDT 2026
https://github.com/0xFE4415 created https://github.com/llvm/llvm-project/pull/196541
When deleting or extracting with -N, member counting uses case sensitive
member arguments while path matching uses normalized paths.
This causes an issue(on Windows): if you have files: foo.txt and FOO.txt, you can only extract one of them when using -N 1, and using -N 2 results in error.
Tested on Linux(WSL):
$ build/bin/llvm-lit llvm/test/tools/llvm-ar/ (79 passed, 4 unsupported)
Total Discovered Tests: 83
Unsupported: 4 (4.82%)
Passed : 79 (95.18%)
Tested on Windows:
PS1> python build/bin/llvm-lit.py llvm/test/tools/llvm-ar/
Total Discovered Tests: 83
Unsupported: 4 (4.82%)
Passed : 79 (95.18%)
>From ef5eb93be6c57324a338e445ec61bd4c165409ea Mon Sep 17 00:00:00 2001
From: Luna <259395 at student.pwr.edu.pl>
Date: Sat, 2 May 2026 22:43:39 +0200
Subject: [PATCH 1/2] extended test
---
.../test/tools/llvm-ar/windows-name-case.test | 31 +++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/llvm/test/tools/llvm-ar/windows-name-case.test b/llvm/test/tools/llvm-ar/windows-name-case.test
index 970a3e616d3c7..4b93e203ca21c 100644
--- a/llvm/test/tools/llvm-ar/windows-name-case.test
+++ b/llvm/test/tools/llvm-ar/windows-name-case.test
@@ -27,3 +27,34 @@
# RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=EMPTY --implicit-check-not {{.}}
EMPTY: !<thin>
+
+# File instance counting should respect Windows case-insensitive name matching.
+# Otherwise, if you have foo.txt and FOO.TXT, "-N 2 foo.txt" fails with because
+# file is not found.
+
+# RUN: mkdir -p %t/a %t/b
+# RUN: echo first > %t/a/foo.txt
+# RUN: echo second > %t/b/FOO.TXT
+# RUN: llvm-ar rc %t/count-case.a %t/a/foo.txt %t/b/FOO.TXT
+
+# RUN: mkdir -p %t/out1 %t/out2
+# RUN: llvm-ar xN 1 --output %t/out1 %t/count-case.a foo.txt
+# RUN: cat %t/out1/foo.txt | FileCheck %s --check-prefix=EXTRACT-FIRST
+# RUN: llvm-ar xN 2 --output %t/out2 %t/count-case.a foo.txt
+# RUN: cat %t/out2/FOO.TXT | FileCheck %s --check-prefix=EXTRACT-SECOND
+# RUN: not llvm-ar xN 3 --output %t/out2 %t/count-case.a foo.txt 2>&1 | FileCheck %s --check-prefix=EXTRACT-NOT-FOUND
+
+# EXTRACT-FIRST: first
+# EXTRACT-SECOND: second
+# EXTRACT-NOT-FOUND: error: 'foo.txt' was not found
+
+# RUN: rm -f %t/delete-count.a
+# RUN: llvm-ar rc %t/delete-count.a %t/a/foo.txt %t/b/FOO.TXT
+# RUN: llvm-ar dN 2 %t/delete-count.a foo.txt
+# RUN: llvm-ar t %t/delete-count.a | FileCheck %s --check-prefix=DELETE-SECOND
+# RUN: llvm-ar dN 1 %t/delete-count.a FOO.TXT
+# RUN: llvm-ar t %t/delete-count.a | FileCheck %s --check-prefix=DELETE-EMPTY --allow-empty
+
+# DELETE-SECOND: foo.txt
+# DELETE-SECOND-NOT: FOO.TXT
+# DELETE-EMPTY-NOT: foo.txt
>From 8b9e7cdb3ba2dcc1c064033391066f1c1f09464e Mon Sep 17 00:00:00 2001
From: Luna <259395 at student.pwr.edu.pl>
Date: Sat, 2 May 2026 22:43:39 +0200
Subject: [PATCH 2/2] Fix llvm-ar CountParam matching for normalized paths.
---
llvm/tools/llvm-ar/llvm-ar.cpp | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 320a903b59e87..7f4ff0c599208 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -713,8 +713,11 @@ static void performReadOperation(ArchiveOperation Operation,
});
if (I == Members.end())
continue;
- if (CountParam && ++MemberCount[Name] != CountParam)
- continue;
+ if (CountParam) {
+ std::string CountKey = normalizePath(*I);
+ if (++MemberCount[CountKey] != CountParam)
+ continue;
+ }
Members.erase(I);
}
@@ -854,14 +857,20 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
if (Operation == QuickAppend || Members.empty())
return IA_AddOldMember;
- auto MI = find_if(Members, [Name](StringRef Path) {
+ std::string CountKey;
+ auto MI = find_if(Members, [Name, &CountKey](StringRef Path) {
+ SmallString<128> MatchPath(Path);
if (Thin && !sys::path::is_absolute(Path)) {
Expected<std::string> PathOrErr =
computeArchiveRelativePath(ArchiveName, Path);
- return comparePaths(Name, PathOrErr ? *PathOrErr : Path);
- } else {
- return comparePaths(Name, Path);
+ if (PathOrErr) {
+ MatchPath = *PathOrErr;
+ }
}
+ if (!comparePaths(Name, MatchPath))
+ return false;
+ CountKey = normalizePath(MatchPath);
+ return true;
});
if (MI == Members.end())
@@ -870,7 +879,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
Pos = MI;
if (Operation == Delete) {
- if (CountParam && ++MemberCount[Name] != CountParam)
+ if (CountParam && ++MemberCount[CountKey] != CountParam)
return IA_AddOldMember;
return IA_Delete;
}
More information about the llvm-commits
mailing list