Skip to content

Fix/memory resource safety#627

Open
gfnord wants to merge 4 commits into
T-Troll:masterfrom
gfnord:fix/memory-resource-safety
Open

Fix/memory resource safety#627
gfnord wants to merge 4 commits into
T-Troll:masterfrom
gfnord:fix/memory-resource-safety

Conversation

@gfnord

@gfnord gfnord commented Jun 25, 2026

Copy link
Copy Markdown

Summary

A set of memory- and resource-safety fixes across four files. No behavioural change on the success path; each change closes a leak, a use-after-free risk, or an uninitialized read on a failure/exception path.

Changes

Common/Common.cpp — Update check buffer exception safety

The 255-byte char buffer used by CUpdateCheck was allocated with raw new[] and freed only after several std::string operations that can throw bad_alloc on OOM. Switched to std::unique_ptr<char[]> so the buffer cannot leak on the exception path. The 254-byte GitHub-API read through the same WinINet handles is unchanged.

LightFX/LightFX.cpp — Init resource cleanup on failure paths

Two fixes in LFX_Initialize:

  • NODEVS path: when no devices are detected, the previous code returned LFX_ERROR_NODEVS leaving the worker thread, its two events, and afx_dev allocated for process lifetime. Now the NODEVS branch stops the worker (SetEvent + WaitForSingleObject + CloseHandle on the thread and both events) and then deletes afx_dev. CLightsProc at LightFX.cpp:54 dereferences afx_dev with no NULL guard, so the thread is stopped before afx_dev is freed, and a comment documents the invariant so future cleanup passes do not reorder it into a use-after-free.
  • CreateThread failure path: if CreateThread in the same block returned NULL, the two CreateEvent handles created moments earlier leaked and afx_dev was left orphaned. The new if (!updateThread) branch closes both events, NULLs them, frees afx_dev, and returns LFX_ERROR_NOINIT.

alienfx-gui/HapticsDialog.cpp — Drop redundant DeleteDC

DrawFreq() already returns the window DC via ReleaseDC(hysto, hdc_r), so the following DeleteDC(hdc_r) was a no-op on an already-released handle (DeleteDC is for CreateCompatibleDC results, not GetDC results). Removed the redundant line.

alienfx-gui/WSAudioIn.cpp — Initialize COM enumerator, RAII FFT buffers

Two fixes:

  • GetDefaultMultimediaDevice() declared IMMDeviceEnumerator* pEnumerator uninitialized, then tested it with if (pEnumerator) after CoCreateInstance. If CoCreateInstance failed, the out-param was not guaranteed NULL and the check read indeterminate stack memory. Now initialized to NULL.
  • FFTProc() allocated kiss_cfg + three new[] arrays without rollback; a bad_alloc in any later allocation leaked the earlier ones, and kiss_fftr_alloc returning NULL caused a NULL dereference in kiss_fftr below. Switched the three arrays to std::unique_ptr<T[]>, moved kiss_fftr_alloc after them, and added a NULL check that returns early. Updated the kiss_fftr call site to use .get(). Removed the three matching delete[] lines at function exit; kiss_fft_free is retained.

Notes

  • No public API or success-path behaviour changes.
  • Resource lifetimes are now exception-safe where they were not before.

gfnord added 4 commits June 24, 2026 17:17
The 255-byte char buffer used by CUpdateCheck was allocated with raw new[] and freed only after several std::string operations that can throw bad_alloc on OOM. Switched to std::unique_ptr<char[]> so the buffer cannot leak on the exception path. No behavioural change in the success path; the same 254-byte GitHub-API read still happens through the same WinINet handles.
Two fixes in LFX_Initialize.

NODEVS path: when no devices are detected, LFX_Initialize previously returned LFX_ERROR_NODEVS leaving the worker thread, its two events, and afx_dev allocated for process lifetime. Now the NODEVS branch stops the worker (SetEvent + WaitForSingleObject + CloseHandle on the thread and both events) and then deletes afx_dev. CLightsProc at LightFX.cpp:54 dereferences afx_dev with no NULL guard, so the thread MUST be stopped before afx_dev is freed; the new code does it in that order and a comment documents the invariant so future cleanup passes don't reorder it back into a use-after-free.

CreateThread failure path: if CreateThread inside the same block returned NULL, the two CreateEvent handles created moments earlier leaked and afx_dev was left orphaned. The new if (!updateThread) branch closes both events, NULLs them, frees afx_dev, and returns LFX_ERROR_NOINIT.
DrawFreq() already returns the window DC via ReleaseDC(hysto, hdc_r), so the following DeleteDC(hdc_r) was a no-op on an already-released handle (DeleteDC is for CreateCompatibleDC results, not GetDC results). Removed the redundant line.
Two fixes in WSAudioIn.cpp.

GetDefaultMultimediaDevice() declared IMMDeviceEnumerator* pEnumerator uninitialized then tested it with if (pEnumerator) after CoCreateInstance. If CoCreateInstance failed the out-param was not guaranteed NULL and the check read indeterminate stack memory. Now initialized to NULL.

FFTProc() allocated kiss_cfg + three new[] arrays without rollback; a bad_alloc in any later allocation leaked the earlier ones, and kiss_fftr_alloc returning NULL caused a NULL dereference in kiss_fftr below. Switched the three arrays to std::unique_ptr<T[]>, moved kiss_fftr_alloc after them, and added a NULL check that returns early. Updated the kiss_fftr call site to use .get(). Removed the three matching delete[] lines at function exit; kiss_fft_free is retained.
gfnord added a commit to gfnord/alienfx-tools that referenced this pull request Jun 25, 2026
Memory- and resource-safety fixes (see PR T-Troll#627):
- Common/Common.cpp: RAII buffer in CUpdateCheck
- LightFX/LightFX.cpp: LFX_Initialize cleanup on NODEVS + CreateThread failure
- alienfx-gui/HapticsDialog.cpp: drop redundant DeleteDC
- alienfx-gui/WSAudioIn.cpp: NULL-init COM enumerator, RAII FFT buffers
@gfnord gfnord closed this Jun 25, 2026
@gfnord gfnord deleted the fix/memory-resource-safety branch June 25, 2026 00:25
@gfnord gfnord restored the fix/memory-resource-safety branch June 25, 2026 00:26
@gfnord gfnord reopened this Jun 25, 2026
@gfnord gfnord mentioned this pull request Jun 25, 2026
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