From 50de1c4ee7a56e47a06c44769cea5aa2457a829b Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 21 Jan 2026 00:16:24 -0800 Subject: Improve handling of nulls in MultiSzInsertString and MultiSzLen Resolves 7311 --- src/libs/dutil/WixToolset.DUtil/strutil.cpp | 31 +++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src/libs/dutil/WixToolset.DUtil/strutil.cpp') diff --git a/src/libs/dutil/WixToolset.DUtil/strutil.cpp b/src/libs/dutil/WixToolset.DUtil/strutil.cpp index 0a00c690..013c1b12 100644 --- a/src/libs/dutil/WixToolset.DUtil/strutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/strutil.cpp @@ -1872,9 +1872,14 @@ NOTE: returns 0 if the multisz in not properly terminated with two nulls extern "C" HRESULT DAPI MultiSzLen( __in_ecount(*pcch) __nullnullterminated LPCWSTR pwzMultiSz, __out SIZE_T* pcch -) + ) { Assert(pcch); + if (!pwzMultiSz) + { + *pcch = 0; + return S_OK; + } HRESULT hr = S_OK; LPCWSTR wz = pwzMultiSz; @@ -1941,10 +1946,10 @@ extern "C" HRESULT DAPI MultiSzPrepend( hr = ::StringCchLengthW(pwzInsert, STRSAFE_MAX_CCH, reinterpret_cast(&cchInsert)); StrExitOnRootFailure(hr, "failed to get length of insert string"); - cchResult = cchInsert + cchMultiSz + 1; + cchResult = cchInsert + (cchMultiSz ? cchMultiSz : 1) + 1; // Allocate the result buffer - hr = StrAlloc(&pwzResult, cchResult + 1); + hr = StrAlloc(&pwzResult, cchResult); StrExitOnFailure(hr, "failed to allocate result string"); // Prepend @@ -1954,8 +1959,7 @@ extern "C" HRESULT DAPI MultiSzPrepend( // If there was no MULTISZ, double null terminate our result, otherwise, copy the MULTISZ in if (0 == cchMultiSz) { - pwzResult[cchResult] = L'\0'; - ++cchResult; + pwzResult[cchResult - 2] = L'\0'; } else { @@ -1967,6 +1971,7 @@ extern "C" HRESULT DAPI MultiSzPrepend( } // Set the result + pwzResult[cchResult - 1] = L'\0'; *ppwzMultiSz = pwzResult; if (pcchMultiSz) @@ -2257,19 +2262,29 @@ extern "C" HRESULT DAPI MultiSzInsertString( // // Insert the string // - cchResult = cchMultiSz + cchString + 1; + cchResult = (cchMultiSz ? cchMultiSz : 1) + cchString + 1; hr = StrAlloc(&pwzResult, cchResult); StrExitOnFailure(hr, "failed to allocate result string for MULTISZ insert"); // Copy the part before the insert - ::CopyMemory(pwzResult, *ppwzMultiSz, cchProgress * sizeof(WCHAR)); + if (cchProgress) + { + ::CopyMemory(pwzResult, *ppwzMultiSz, cchProgress * sizeof(WCHAR)); + } // Copy the insert part ::CopyMemory(pwzResult + cchProgress, pwzInsert, (cchString + 1) * sizeof(WCHAR)); // Copy the part after the insert - ::CopyMemory(pwzResult + cchProgress + cchString + 1, wz, (cchMultiSz - cchProgress) * sizeof(WCHAR)); + if (cchMultiSz > cchProgress) + { + ::CopyMemory(pwzResult + cchProgress + cchString + 1, wz, (cchMultiSz - cchProgress) * sizeof(WCHAR)); + } + + // Ensure double-null termination + pwzResult[cchResult - 1] = L'\0'; + pwzResult[cchResult - 2] = L'\0'; // Free the old buffer ReleaseNullStr(*ppwzMultiSz); -- cgit v1.2.3-55-g6feb