Skip to content

Commit

Permalink
Linux: Implement prefix-counted BSTR allocation in SysAllocStringLen (m…
Browse files Browse the repository at this point in the history
…icrosoft#3250)

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
  • Loading branch information
MarijnS95 authored Nov 12, 2020
1 parent a39e52d commit 2ade6f8
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
10 changes: 6 additions & 4 deletions include/dxc/Support/WinAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@
#define CoTaskMemAlloc malloc
#define CoTaskMemFree free

#define SysFreeString free
#define SysAllocStringLen(ptr, size) \
(wchar_t *)realloc(ptr, (size + 1) * sizeof(wchar_t))

#define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))

#define _countof(a) (sizeof(a) / sizeof(*(a)))
Expand Down Expand Up @@ -916,6 +912,12 @@ class CHeapPtr : public CHeapPtrBase<T, Allocator> {

#define CComHeapPtr CHeapPtr

//===--------------------------- BSTR Allocation --------------------------===//

void SysFreeString(BSTR bstrString);
// Allocate string with length prefix
BSTR SysAllocStringLen(const OLECHAR *strIn, UINT ui);

//===--------------------- UTF-8 Related Types ----------------------------===//

// Code Page
Expand Down
30 changes: 30 additions & 0 deletions lib/DxcSupport/WinAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ void *CAllocator::Reallocate(void *p, size_t nBytes) throw() {
void *CAllocator::Allocate(size_t nBytes) throw() { return malloc(nBytes); }
void CAllocator::Free(void *p) throw() { free(p); }

//===--------------------------- BSTR Allocation --------------------------===//

void SysFreeString(BSTR bstrString) {
if (bstrString)
free((void *)((uintptr_t)bstrString - sizeof(uint32_t)));
}

// Allocate string with length prefix
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/bstr
BSTR SysAllocStringLen(const OLECHAR *strIn, UINT ui) {
uint32_t *blobOut =
(uint32_t *)malloc(sizeof(uint32_t) + (ui + 1) * sizeof(OLECHAR));

if (!blobOut)
return nullptr;

// Size in bytes without trailing NULL character
blobOut[0] = ui * sizeof(OLECHAR);

BSTR strOut = (BSTR)&blobOut[1];

if (strIn)
memcpy(strOut, strIn, blobOut[0]);

// Write trailing NULL character:
strOut[ui] = 0;

return strOut;
}

//===---------------------- Char converstion ------------------------------===//

const char *CPToLocale(uint32_t CodePage) {
Expand Down

0 comments on commit 2ade6f8

Please sign in to comment.