Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle race condition in PdhUtil#PdhEnumObjectItems #1442

Merged
merged 1 commit into from Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -13,6 +13,7 @@ Features
Bug Fixes
---------
* [#1438](https://github.com/java-native-access/jna/pull/1438): Handle arrays in structures with differing size - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1442](https://github.com/java-native-access/jna/issues/1442): Handle race condition in `c.s.j.p.win32.PdhUtil#PdhEnumObjectItems` - [@dbwiddis](https://github.com/dbwiddis).

Important Changes
-----------------
Expand Down
39 changes: 30 additions & 9 deletions contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java
Expand Up @@ -162,7 +162,9 @@ public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String
List<String> counters = new ArrayList<String>();
List<String> instances = new ArrayList<String>();

// Call once to get string lengths
// Call once to get counter and instance string lengths
// If zero on input and the object exists, the function returns PDH_MORE_DATA
// and sets these parameters to the required buffer size.
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
int result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
Expand All @@ -174,16 +176,35 @@ public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String
Memory mszCounterList = null;
Memory mszInstanceList = null;

if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}
// A race condition may exist for some instance lists such as processes or
// threads which may result in PDH_MORE_DATA.
do {
if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}

if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}
if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}

result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);
result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);
if (result == Pdh.PDH_MORE_DATA) {
// If the specified size on input is greater than zero but less than the
// required size, you should not rely on the returned size to reallocate the
// buffer.
if (mszCounterList != null) {
long tooSmallSize = mszCounterList.size() / CHAR_TO_BYTES;
pcchCounterListLength.setValue(new DWORD(tooSmallSize + 1024));
mszCounterList.close();
}
if (mszInstanceList != null) {
long tooSmallSize = mszInstanceList.size() / CHAR_TO_BYTES;
pcchInstanceListLength.setValue(new DWORD(tooSmallSize + 1024));
mszInstanceList.close();
}
}
} while (result == Pdh.PDH_MORE_DATA);

if(result != WinError.ERROR_SUCCESS) {
throw new PdhException(result);
Expand Down