RFR: 8350869: os::stat doesn't follow symlinks on Windows [v3]

David Holmes dholmes at openjdk.org
Fri May 16 06:18:57 UTC 2025


On Thu, 15 May 2025 13:38:20 GMT, Anton Artemov <duke at openjdk.org> wrote:

>> This PR addresses an issue on Windows, where a class file could not be loaded by a symbolic link. 
>> 
>> I added a check if a wide path is a symbolic link (soft one) and a method for dereferencing. Both os::stat() and os::open() on Windows now can handle such links.
>> 
>> Tested in tiers 1-3. A separate test added.
>
> Anton Artemov has updated the pull request incrementally with one additional commit since the last revision:
> 
>   8350869: Addressed reviewer's comments

Thanks for the updates, a number of style issues remaining, and some more error checking queries/concerns.

src/hotspot/os/windows/os_windows.cpp line 4616:

> 4614: static bool is_symbolic_link(const wchar_t* wide_path) {
> 4615:   WIN32_FIND_DATAW fd;
> 4616:   HANDLE f = ::FindFirstFileW(wide_path, &fd);

Do you need to check for errors here?

src/hotspot/os/windows/os_windows.cpp line 4625:

> 4623: static WCHAR* get_path_to_target(const wchar_t* wide_path) {
> 4624:   HANDLE hFile = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ, nullptr,
> 4625:     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

Suggestion:

  HANDLE hFile = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ, nullptr,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

src/hotspot/os/windows/os_windows.cpp line 4625:

> 4623: static WCHAR* get_path_to_target(const wchar_t* wide_path) {
> 4624:   HANDLE hFile = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ, nullptr,
> 4625:     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

Suggestion:

  HANDLE hFile = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ, nullptr,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

Parameters should line up

src/hotspot/os/windows/os_windows.cpp line 4628:

> 4626: 
> 4627:   const size_t target_path_size = ::GetFinalPathNameByHandleW(hFile, nullptr, 0,
> 4628:     FILE_NAME_NORMALIZED);

Suggestion:

  const size_t target_path_size = ::GetFinalPathNameByHandleW(hFile, nullptr, 0,  FILE_NAME_NORMALIZED);

Or else align parameters

src/hotspot/os/windows/os_windows.cpp line 4637:

> 4635:   WCHAR* path_to_target = NEW_C_HEAP_ARRAY(WCHAR, target_path_size + 1, mtInternal);
> 4636: 
> 4637:   ::GetFinalPathNameByHandleW(hFile, path_to_target, static_cast<DWORD>(target_path_size + 1),

Maybe save the return value and assert it is the expected one.

src/hotspot/os/windows/os_windows.cpp line 4721:

> 4719: 
> 4720:   if (is_symlink)
> 4721:   {

Suggestion:

  if (is_symlink) {

src/hotspot/os/windows/os_windows.cpp line 4724:

> 4722:     path_to_target = get_path_to_target(wide_path);
> 4723:     if (path_to_target == nullptr)
> 4724:     {

Suggestion:

    if (path_to_target == nullptr) {

src/hotspot/os/windows/os_windows.cpp line 4733:

> 4731: 
> 4732:   WIN32_FILE_ATTRIBUTE_DATA file_data;;
> 4733:   BOOL bret = ::GetFileAttributesExW(is_symlink && path_to_target != nullptr ? path_to_target : wide_path, GetFileExInfoStandard, &file_data);

Didn't we already return if `path_to_target` is null?

src/hotspot/os/windows/os_windows.cpp line 4738:

> 4736: 
> 4737:   if (!bret) {
> 4738:     errno = ::GetLastError();

Pre-existing but `GetLastError` could have been reset by the time we get here depending on what is inside `os::free`.

src/hotspot/os/windows/os_windows.cpp line 4931:

> 4929: 
> 4930:   if (is_symlink)
> 4931:   {

Suggestion:

  if (is_symlink) {

src/hotspot/os/windows/os_windows.cpp line 4934:

> 4932:     path_to_target = get_path_to_target(wide_path);
> 4933:     if (path_to_target == nullptr)
> 4934:     {

Suggestion:

    if (path_to_target == nullptr) {

src/hotspot/os/windows/os_windows.cpp line 4947:

> 4945: 
> 4946:   if (fd == -1) {
> 4947:     errno = ::GetLastError();

Again `GetLastError` may have been reset

test/hotspot/jtreg/runtime/LoadClass/TestSymlinkLoad.java line 67:

> 65:         OutputAnalyzer output = new OutputAnalyzer(pb.start());
> 66:         output.shouldContain("Hello World")
> 67:             .shouldHaveExitValue(0);

Style nit: The dots should align

test/hotspot/jtreg/runtime/LoadClass/TestSymlinkLoad.java line 67:

> 65:         OutputAnalyzer output = new OutputAnalyzer(pb.start());
> 66:         output.shouldContain("Hello World")
> 67:             .shouldHaveExitValue(0);

Please align dots on chained invocations. Thanks

test/hotspot/jtreg/runtime/LoadClass/TestSymlinkLoad.java line 80:

> 78:         output = new OutputAnalyzer(pb.start());
> 79:         output.shouldContain("Hello World")
> 80:             .shouldHaveExitValue(0);

Style nit: The dots should align

-------------

Changes requested by dholmes (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/25233#pullrequestreview-2845575955
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092380983
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092376411
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092381874
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092382518
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092386369
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092386979
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092387226
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092388895
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092392278
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092392674
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092392964
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092393514
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092378056
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092394571
PR Review Comment: https://git.openjdk.org/jdk/pull/25233#discussion_r2092378608


More information about the hotspot-runtime-dev mailing list