-
Notifications
You must be signed in to change notification settings - Fork 709
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
Linux: Implement prefix-counted BSTR allocation in SysAllocStringLen #3250
Conversation
While this prefix may be an implementation detail the BSTR type guarantees to be able to store NULL values without accidentally truncating the string, hence its length must be available to replace the usual NULL terminator. This string length in bytes is stored in the four bytes preceding a BSTR pointer [1], whose value can be retrieved using SysStringLen. This commit implements the type in the same way in WinAdapter such that users of the functions returning a BSTR (currently only in dxcisense) can expect and use the type in the same way on Linux as they would on Windows. While this function and type currently only seem to be involved in names and logging where NULLs are unlikely, it is good practice to mirror the Windows type exactly for future-proofing. Besides, SysAllocStringLen does not specify anything about taking ownership of strIn so the realloc here is wrong either way. [1]: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/bstr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks @MarijnS95
@ehsannas Thanks for merging this quickly! Keep in mind that this is a slightly breaking change for Unix users that are On a similar note, is there anything I can do to give #3062 the same approval + merge treatment? |
Yeah I understand. If anyone out there is |
@ehsannas The problem is that Hence my request to export these functions (including |
When running valgrind over a program using `DxcIntelliSense` (to validate our own deallocations [1]) a bunch of mismatching `new` with `free()` show up: Mismatched free() / delete / delete [] at 0x483B9AB: free (vg_replace_malloc.c:538) by 0x52B06A8: IMalloc::Free(void*) (WinAdapter.cpp:34) by 0x6DC7D19: DxcTranslationUnit::Release() (dxcisenseimpl.h:308) by 0x14278E: com_rs::unknown::IUnknown::release (unknown.rs:55) [...] Address 0x4c3c930 is 0 bytes inside a block of size 40 alloc'd at 0x483B07F: operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:385) by 0x6DC06EB: DxcIndex::ParseTranslationUnit(char const*, char const* const*, int, IDxcUnsavedFile**, unsigned int, DxcTranslationUnitFlags, IDxcTranslationUnit**) (dxcisenseimpl.cpp:1192) by 0x13020A: hassle_rs::intellisense::ffi::IDxcIndex::parse_translation_unit (macros.rs:108) by 0x119B74: hassle_rs::intellisense::wrapper::DxcIndex::parse_translation_unit (wrapper.rs:101) [...] And so on for the other intellisense classes. All these classes have `DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL` which deallocates `this` on the associated `m_pMalloc` with `free()`: The "TM" version keep an IMalloc field that, if not null, indicate ownership of 'this' and of any allocations used during release. Yet are allocated using `new`, resulting in this mismatch. The solution is to follow a similar approach as the introduction of `IMalloc` to `DxcIntelliSense` in d5bb308 by rewriting all classes to take an `IMalloc *` in the constructor and invoking it either through `::Alloc` from `DXC_MICROCOM_TM_ALLOC` or `CreateOnMalloc`. [1]: microsoft#3250 (comment)
When running valgrind over a program using `DxcIntelliSense` (to validate our own deallocations [1]) a bunch of mismatching `new` with `free()` show up: Mismatched free() / delete / delete [] at 0x483B9AB: free (vg_replace_malloc.c:538) by 0x52B06A8: IMalloc::Free(void*) (WinAdapter.cpp:34) by 0x6DC7D19: DxcTranslationUnit::Release() (dxcisenseimpl.h:308) by 0x14278E: com_rs::unknown::IUnknown::release (unknown.rs:55) [...] Address 0x4c3c930 is 0 bytes inside a block of size 40 alloc'd at 0x483B07F: operator new(unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:385) by 0x6DC06EB: DxcIndex::ParseTranslationUnit(char const*, char const* const*, int, IDxcUnsavedFile**, unsigned int, DxcTranslationUnitFlags, IDxcTranslationUnit**) (dxcisenseimpl.cpp:1192) by 0x13020A: hassle_rs::intellisense::ffi::IDxcIndex::parse_translation_unit (macros.rs:108) by 0x119B74: hassle_rs::intellisense::wrapper::DxcIndex::parse_translation_unit (wrapper.rs:101) [...] And so on for the other intellisense classes. All these classes have `DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL` which deallocates `this` on the associated `m_pMalloc` with `free()`: The "TM" version keep an IMalloc field that, if not null, indicate ownership of 'this' and of any allocations used during release. Yet are allocated using `new`, resulting in this mismatch. The solution is to follow a similar approach as the introduction of `IMalloc` to `DxcIntelliSense` in d5bb308 by rewriting all classes to take an `IMalloc *` in the constructor and invoking it either through `::Alloc` from `DXC_MICROCOM_TM_ALLOC` or `CreateOnMalloc`. [1]: #3250 (comment)
@ehsannas I'm afraid I forgot to tag you in the reply above and it seems like you have not received a notification for it. Are there any objections to exporting aforementioned shimmed functions for use on non-Windows platforms? |
I'm afraid I'm not following what you exactly mean by exporting them. Would you please make a separate PR so that discussions can take place there? Thanks |
We [recently] fixed memory leaks when calling into the intellisense part of DXC and made the decision shortly after merging to [implement null-invariant `BSTR`s properly] in DXC's shimmed type for non-Windows, which was promptly accepted. Currently our implementation of `SysFreeString` together with that PR segfaults because it frees the pointer at offset `+4` of the allocation. That is corrected together with `SysStringLen` now reading the size of the string from this prefix instead of looking for a (wrong!) null character. At least our Windows and Linux implementation `utils.rs` is the same again. [recently]: #10 [implement null-invariant `BSTR`s properly]: microsoft/DirectXShaderCompiler#3250
We [recently] fixed memory leaks when calling into the intellisense part of DXC and made the decision shortly after merging to [implement null-invariant `BSTR`s properly] in DXC's shimmed type for non-Windows, which was promptly accepted. Currently our implementation of `SysFreeString` together with that PR segfaults because it frees the pointer at offset `+4` of the allocation. That is corrected together with `SysStringLen` now reading the size of the string from this prefix instead of looking for a (wrong!) null termination character. At least our Windows and Linux implementation `utils.rs` is the same again. [recently]: #10 [implement null-invariant `BSTR`s properly]: microsoft/DirectXShaderCompiler#3250
We [recently] fixed memory leaks when calling into the intellisense part of DXC and made the decision shortly after merging to [implement null-invariant `BSTR`s properly] in DXC's shimmed type for non-Windows, which was promptly accepted. Currently our implementation of `SysFreeString` together with that PR segfaults because it frees the pointer at offset `+4` of the allocation. That is corrected together with `SysStringLen` now reading the size of the string from this prefix instead of looking for a (wrong!) null termination character. At least our Windows and Linux implementation `utils.rs` is the same again. [recently]: #10 [implement null-invariant `BSTR`s properly]: microsoft/DirectXShaderCompiler#3250
…ize (#11) We [recently] fixed memory leaks when calling into the intellisense part of DXC and made the decision shortly after merging to [implement null-invariant `BSTR`s properly] in DXC's shimmed type for non-Windows, which was promptly accepted. Currently our implementation of `SysFreeString` together with that PR segfaults because it frees the pointer at offset `+4` of the allocation. That is corrected together with `SysStringLen` now reading the size of the string from this prefix instead of looking for a (wrong!) null termination character. At least our Windows and Linux implementation `utils.rs` is the same again. [recently]: #10 [implement null-invariant `BSTR`s properly]: microsoft/DirectXShaderCompiler#3250
While this prefix may be an implementation detail the
BSTR
type guarantees to be able to storeNULL
values without accidentally truncating the string, hence its length must be available to replace the usualNULL
terminator. This string length in bytes is stored in the four bytes preceding aBSTR
pointer 1, whose value can be retrieved usingSysStringLen
.This commit implements the type in the same way in
WinAdapter
such that users of the functions returning aBSTR
(currently only indxcisense
) can expect and use the type in the same way on Linux as they would on Windows.While this function and type currently only seem to be involved in names and logging where
NULL
s are unlikely, it is good practice to mirror the Windows type exactly for future-proofing.Besides, SysAllocStringLen does not specify anything about taking ownership of
strIn
so therealloc
here is wrong either way.