Skip to content

Fix undefined behaviour and error handling in the HidModifier config path - #81

Open
nutbolt9 wants to merge 1 commit into
sboys3:mainfrom
nutbolt9:fix/hid-config-roundtrip
Open

Fix undefined behaviour and error handling in the HidModifier config path#81
nutbolt9 wants to merge 1 commit into
sboys3:mainfrom
nutbolt9:fix/hid-config-roundtrip

Conversation

@nutbolt9

@nutbolt9 nutbolt9 commented Aug 1, 2026

Copy link
Copy Markdown

Three independent fixes in HidModifier, found while investigating a Dream Air that intermittently failed to enumerate. Each is a separate commit.

  1. Uninitialised HidDeviceInfo members (e450067)
    AddDevice default-initialises a HidDeviceInfo, so newLighthouseConfig, newLighthouseConfigLength and newLighthouseConfigOffset are indeterminate. ReadLighthouseConfig only assigns newLighthouseConfig on the path where it rewrites the config, so all three early returns — failed feature report, size > 20000, failed decompress — leave the pointer holding stack garbage. HidGetFeatureReportHook then tests it against nullptr and memcpys from it, and Delete() passes it to delete[].
    This is reachable in practice: a driver log showing Failed to decompress lighthouse config was immediately followed by Driver lighthouse has no suitable devices and VRInitError_Init_HmdNotFound.

  2. Failed recompression served anyway (b34102f)
    compress() returning non-Z_OK was logged, but execution continued and assigned the partially written buffer to info.newLighthouseConfig. The hook then served that to driver_lighthouse in place of the device's own config, so a failed recompress produced a corrupt config rather than no change. Now the buffer is freed and newLighthouseConfig left null, so the hook passes through to the original.

  3. Short-buffer guard in HidGetFeatureReportHook (03cb3a1)
    The hook read data[0] and wrote data[1..2] without checking length. Since length is a size_t, a caller passing 0 or 1 also underflows the (length - 2) that sizes the chunk copy, giving a negative toCopy that memcpy takes as a huge value. driver_lighthouse supplies 65 in practice, so this is hardening rather than an observed fault.

Testing: all three compile clean on v143 / MSVC 14.44, Release x64. They have not been runtime-tested — I don't have HidModifierPrivate.cpp, so a local build isn't feature-equivalent to a release and wouldn't be a meaningful test. Happy to test a build if that's useful.

The hook read data[0] and wrote data[1..2] without checking length. length is a size_t, so a caller passing 0 or 1 also underflowed the (length - 2) used to size the chunk copy, producing a negative toCopy that memcpy takes as a very large size_t.

driver_lighthouse supplies 65 in practice, so this is hardening rather than an observed fault, but the hook runs for every hid_get_feature_report call in that module and the failure mode is heap corruption.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nutbolt9
nutbolt9 force-pushed the fix/hid-config-roundtrip branch from 03cb3a1 to 650913b Compare August 11, 2026 10:23
@nutbolt9

Copy link
Copy Markdown
Author

Rebased onto current main and reduced this to a single commit.

The two other fixes it originally carried are already covered on main:

  • falling back to the unmodified config when compress fails — handled by the early return configStr; in HidModifier.cpp
  • initialising the HidDeviceInfo members — now done at the declarations in HidModifier.h

So this is down to the one remaining item. HidGetFeatureReportHook reads data[0] and writes data[1]/data[2] before checking length. length is a size_t, so a caller passing 0 or 1 also underflows the length - 2 that sizes the chunk copy, giving a negative toCopy that memcpy takes as a very large size_t.

driver_lighthouse supplies 65 in practice, so this is hardening rather than an observed fault — but the hook runs for every hid_get_feature_report call in that module and the failure mode is heap corruption.

+4 −1, one file. Happy to drop it if you'd rather not carry the check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant