Skip to content

Make win32_pathbyaddr more reliable#30705

Open
nhorman wants to merge 4 commits intoopenssl:masterfrom
nhorman:zendesk-1775
Open

Make win32_pathbyaddr more reliable#30705
nhorman wants to merge 4 commits intoopenssl:masterfrom
nhorman:zendesk-1775

Conversation

@nhorman
Copy link
Copy Markdown
Contributor

@nhorman nhorman commented Apr 7, 2026

A user has reported that win32_pathbyaddr can be unreliable in multithreaded environments. See:

https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot

Specifically they have observed the following behavior, as noted in the above article:

When taking snapshots that include heaps and modules for a process other than the current process, the CreateToolhelp32Snapshot function can fail or return incorrect information for a variety of reasons. For example, if the loader data table in the target process is corrupted or not initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, the function might fail with ERROR_BAD_LENGTH or other error code. Ensure that the target process was not started in a suspended state, and try calling the function again. If the function fails with ERROR_BAD_LENGTH when called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the function again until it succeeds.

This behavior necessitates calling DSO_pathbyaddr mutiple times to get a succesful return code.

win32_pathbyaddr can be made more reliable, avoiding the need for multiple calls by using alternate windows apis that are not/less succeptible to these transient errors in multithreaded environments.

refactor win32_pathbyaddr here to implement that increased reliability.

A user has reported that win32_pathbyaddr can be unreliable in
multithreaded environments. See:

https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot

Specifically they have observed the following behavior, as noted in the
above article:

When taking snapshots that include heaps and modules for a process other than
the current process, the CreateToolhelp32Snapshot function can fail or return
incorrect information for a variety of reasons. For example, if the loader data
table in the target process is corrupted or not initialized, or if the module
list changes during the function call as a result of DLLs being loaded or
unloaded, the function might fail with ERROR_BAD_LENGTH or other error code.
Ensure that the target process was not started in a suspended state, and try
calling the function again. If the function fails with ERROR_BAD_LENGTH when
called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the function again
until it succeeds.

This behavior necessitates calling DSO_pathbyaddr mutiple times to get a
succesful return code.

win32_pathbyaddr can be made more reliable, avoiding the need for multiple calls
by using alternate windows apis that are not/less succeptible to these transient
errors in multithreaded environments.

refactor win32_pathbyaddr here to implement that increased reliability.
@nhorman nhorman self-assigned this Apr 7, 2026
@nhorman nhorman added branch: master Applies to master branch approval: review pending This pull request needs review by a committer labels Apr 7, 2026
@nhorman nhorman moved this to Waiting Review in Development Board Apr 7, 2026
Copy link
Copy Markdown
Contributor

@bob-beck bob-beck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presuming that this will blow up immediately if it doesn't work in some older environments and we have test coverage for such things. probably OK?

but that's a bit of an "if?"

@nhorman
Copy link
Copy Markdown
Contributor Author

nhorman commented Apr 9, 2026

@bob-beck yeah, thats always a possibility, but I checked on all the api calls in question, and they are all supported back to windows xp, save for one (can't remember which), that was introduced in windows server 2000. So I think we're safe here.

Comment thread crypto/dso/dso_win32.c Outdated
Comment thread crypto/dso/dso_win32.c Outdated
return -1;
if (sz <= 0) {
OPENSSL_free(wpath);
return (int)(wlen + 1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we should also return the utf8len computed after this block. Otherwise, the return value will differ. So something like this:

utf8len = WideCharToMultiByte(CP_UTF8, 0, wpath, -1, NULL, 0, NULL, NULL);
if (sz <= 0) {
    OPENSSL_free(wpath);
    return utf8len;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think what you're saying is right. You're correct in that returning wlen + 1 will require a buffer size greater than the size required to store the final converted utf8 string, but we have to do that, because we need a buffer large enough to hold the 2 byte widechar array returned from GetModuleFileNameW().

Comment thread crypto/dso/dso_win32.c Outdated
Copy link
Copy Markdown
Contributor

@Sashan Sashan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good (apart from hModule handle leak.

also this PR kills code for WIN_CE. IMO it's OK (given code goes to master). I'm just saying it loudly here. So people are aware. It kill WIN_CE friendliness here will become a problem later then we can resurrect old code from history and use it under WIN_CE guard.

Comment thread crypto/dso/dso_win32.c
@nhorman nhorman requested a review from Sashan April 16, 2026 14:08
Copy link
Copy Markdown
Contributor

@Sashan Sashan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me. thanks.

Comment thread crypto/dso/dso_win32.c
};
addr = t.p;
HMODULE hModule = NULL;
const DWORD wpathSize = 32768; /* 32768 is the maximum possible path length on Windows */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static const

Comment thread crypto/dso/dso_win32.c
GetLastError());
goto out;
}
wpath = (WCHAR *)OPENSSL_malloc(wpathSize * sizeof(WCHAR));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OPENSSL_malloc_array(wpathSize, sizeof(WCHAR))

@openssl-machine openssl-machine added approval: done This pull request has the required number of approvals and removed approval: review pending This pull request needs review by a committer labels Apr 22, 2026
@github-project-automation github-project-automation Bot moved this from Waiting Review to Waiting Merge in Development Board Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: done This pull request has the required number of approvals branch: master Applies to master branch

Projects

Status: Waiting Merge

Development

Successfully merging this pull request may close these issues.

6 participants