Browse Source

Linux: Implement prefix-counted BSTR allocation in SysAllocStringLen (#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
Marijn Suijten 4 years ago
parent
commit
2ade6f84d6
2 changed files with 36 additions and 4 deletions
  1. 6 4
      include/dxc/Support/WinAdapter.h
  2. 30 0
      lib/DxcSupport/WinAdapter.cpp

+ 6 - 4
include/dxc/Support/WinAdapter.h

@@ -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)))
@@ -916,6 +912,12 @@ public:
 
 #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

+ 30 - 0
lib/DxcSupport/WinAdapter.cpp

@@ -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) {