Skip to content

Commit 1492900

Browse files
committed
Correcting memory allocation in LiteralStringWithPropertyStringPtr::NewFromCString
A confusion between bytes and character count meant that JsCreateString was creating strings that used twice as much space as they needed.
1 parent 45a175d commit 1492900

File tree

4 files changed

+28
-28
lines changed

4 files changed

+28
-28
lines changed

lib/Common/Codex/Utf8Helper.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ namespace utf8
8787
}
8888

8989
inline HRESULT NarrowStringToWideNoAlloc(_In_ LPCSTR sourceString, size_t sourceCount,
90-
__out_ecount(destBufferCount) LPWSTR destString, size_t destBufferCount, _Out_ size_t* destCount)
90+
__out_ecount(destBufferCount) LPWSTR destString, size_t destBufferCount, _Out_ charcount_t* destCount)
9191
{
9292
size_t sourceStart = 0;
9393
size_t cbSourceString = sourceCount;
@@ -123,7 +123,7 @@ namespace utf8
123123

124124
if (sourceStart == sourceCount)
125125
{
126-
*destCount = sourceCount;
126+
*destCount = static_cast<charcount_t>(sourceCount);
127127
destString[sourceCount] = WCHAR(0);
128128
}
129129
else
@@ -160,7 +160,7 @@ namespace utf8
160160
///
161161
template <typename AllocatorFunction>
162162
HRESULT NarrowStringToWide(_In_ AllocatorFunction allocator,_In_ LPCSTR sourceString,
163-
size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destCount, size_t* allocateCount = nullptr)
163+
size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ charcount_t* destCount, size_t* allocateCount = nullptr)
164164
{
165165
size_t cbDestString = (sourceCount + 1) * sizeof(WCHAR);
166166
if (cbDestString < sourceCount) // overflow ?
@@ -184,7 +184,7 @@ namespace utf8
184184
}
185185

186186
template <class Allocator>
187-
HRESULT NarrowStringToWide(_In_ LPCSTR sourceString, size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destCount, size_t* allocateCount = nullptr)
187+
HRESULT NarrowStringToWide(_In_ LPCSTR sourceString, size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ charcount_t* destCount, size_t* allocateCount = nullptr)
188188
{
189189
return NarrowStringToWide(Allocator::allocate, sourceString, sourceCount, destStringPtr, destCount, allocateCount);
190190
}
@@ -205,30 +205,30 @@ namespace utf8
205205

206206
inline HRESULT NarrowStringToWideDynamic(_In_ LPCSTR sourceString, _Out_ LPWSTR* destStringPtr)
207207
{
208-
size_t unused;
208+
charcount_t unused;
209209
return NarrowStringToWide<malloc_allocator>(
210210
sourceString, strlen(sourceString), destStringPtr, &unused);
211211
}
212212

213-
inline HRESULT NarrowStringToWideDynamicGetLength(_In_ LPCSTR sourceString, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destLength)
213+
inline HRESULT NarrowStringToWideDynamicGetLength(_In_ LPCSTR sourceString, _Out_ LPWSTR* destStringPtr, _Out_ charcount_t* destLength)
214214
{
215215
return NarrowStringToWide<malloc_allocator>(
216216
sourceString, strlen(sourceString), destStringPtr, destLength);
217217
}
218218

219-
template <class Allocator, class SrcType, class DstType>
219+
template <class Allocator, class SrcType, class DstType, class CountType>
220220
class NarrowWideStringConverter
221221
{
222222
public:
223223
static size_t Length(const SrcType& src);
224224
static HRESULT Convert(
225-
SrcType src, size_t srcCount, DstType* dst, size_t* dstCount, size_t* allocateCount = nullptr);
225+
SrcType src, size_t srcCount, DstType* dst, CountType* dstCount, size_t* allocateCount = nullptr);
226226
static HRESULT ConvertNoAlloc(
227-
SrcType src, size_t srcCount, DstType dst, size_t dstCount, size_t* written);
227+
SrcType src, size_t srcCount, DstType dst, CountType dstCount, CountType* written);
228228
};
229229

230230
template <class Allocator>
231-
class NarrowWideStringConverter<Allocator, LPCSTR, LPWSTR>
231+
class NarrowWideStringConverter<Allocator, LPCSTR, LPWSTR, charcount_t>
232232
{
233233
public:
234234
// Note: Typically caller should pass in Utf8 string length. Following
@@ -240,23 +240,23 @@ namespace utf8
240240

241241
static HRESULT Convert(
242242
LPCSTR sourceString, size_t sourceCount,
243-
LPWSTR* destStringPtr, size_t* destCount, size_t* allocateCount = nullptr)
243+
LPWSTR* destStringPtr, charcount_t * destCount, size_t* allocateCount = nullptr)
244244
{
245245
return NarrowStringToWide<Allocator>(
246246
sourceString, sourceCount, destStringPtr, destCount, allocateCount);
247247
}
248248

249249
static HRESULT ConvertNoAlloc(
250250
LPCSTR sourceString, size_t sourceCount,
251-
LPWSTR destStringPtr, size_t destCount, size_t* written)
251+
LPWSTR destStringPtr, charcount_t destCount, charcount_t* written)
252252
{
253253
return NarrowStringToWideNoAlloc(
254254
sourceString, sourceCount, destStringPtr, destCount, written);
255255
}
256256
};
257257

258258
template <class Allocator>
259-
class NarrowWideStringConverter<Allocator, LPCWSTR, LPSTR>
259+
class NarrowWideStringConverter<Allocator, LPCWSTR, LPSTR, size_t>
260260
{
261261
public:
262262
// Note: Typically caller should pass in WCHAR string length. Following
@@ -283,14 +283,14 @@ namespace utf8
283283
}
284284
};
285285

286-
template <class Allocator, class SrcType, class DstType>
286+
template <class Allocator, class SrcType, class DstType, class CountType>
287287
class NarrowWideConverter
288288
{
289-
typedef NarrowWideStringConverter<Allocator, SrcType, DstType>
289+
typedef NarrowWideStringConverter<Allocator, SrcType, DstType, CountType>
290290
StringConverter;
291291
private:
292292
DstType dst;
293-
size_t dstCount;
293+
CountType dstCount;
294294
size_t allocateCount;
295295
bool freeDst;
296296

@@ -347,6 +347,6 @@ namespace utf8
347347
}
348348
};
349349

350-
typedef NarrowWideConverter<malloc_allocator, LPCSTR, LPWSTR> NarrowToWide;
351-
typedef NarrowWideConverter<malloc_allocator, LPCWSTR, LPSTR> WideToNarrow;
350+
typedef NarrowWideConverter<malloc_allocator, LPCSTR, LPWSTR, charcount_t> NarrowToWide;
351+
typedef NarrowWideConverter<malloc_allocator, LPCWSTR, LPSTR, size_t> WideToNarrow;
352352
}

lib/Jsrt/Jsrt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4662,7 +4662,7 @@ CHAKRA_API JsCreateString(
46624662
length = strlen(content);
46634663
}
46644664

4665-
if (length > static_cast<CharCount>(-1))
4665+
if (length > MaxCharCount)
46664666
{
46674667
return JsErrorOutOfMemory;
46684668
}

lib/Runtime/Library/ConcatString.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,24 +99,24 @@ namespace Js
9999
}
100100

101101
ScriptContext * scriptContext = library->GetScriptContext();
102-
size_t cbDestString = (charCount + 1) * sizeof(WCHAR);
103-
if ((CharCount)cbDestString < charCount) // overflow
102+
if (charCount > MaxCharCount)
104103
{
105104
Js::JavascriptError::ThrowOutOfMemoryError(scriptContext);
106105
}
107106

108107
Recycler * recycler = library->GetRecycler();
109-
char16* destString = RecyclerNewArrayLeaf(recycler, WCHAR, cbDestString);
108+
char16* destString = RecyclerNewArrayLeaf(recycler, WCHAR, charCount + 1);
110109
if (destString == nullptr)
111110
{
112111
Js::JavascriptError::ThrowOutOfMemoryError(scriptContext);
113112
}
114113

115-
HRESULT result = utf8::NarrowStringToWideNoAlloc(cString, charCount, destString, charCount + 1, &cbDestString);
114+
charcount_t cchDestString = 0;
115+
HRESULT result = utf8::NarrowStringToWideNoAlloc(cString, charCount, destString, charCount + 1, &cchDestString);
116116

117117
if (result == S_OK)
118118
{
119-
return (JavascriptString*) RecyclerNew(library->GetRecycler(), LiteralStringWithPropertyStringPtr, destString, (CharCount)cbDestString, library);
119+
return (JavascriptString*) RecyclerNew(library->GetRecycler(), LiteralStringWithPropertyStringPtr, destString, cchDestString, library);
120120
}
121121

122122
Js::JavascriptError::ThrowOutOfMemoryError(scriptContext);

lib/Runtime/Library/WabtInterface.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ struct Context
1818
ScriptContext* scriptContext;
1919
};
2020

21-
char16* NarrowStringToWide(Context* ctx, const char* src, const size_t* srcSize = nullptr, size_t* dstSize = nullptr)
21+
char16* NarrowStringToWide(Context* ctx, const char* src, const size_t* srcSize = nullptr, charcount_t* dstSize = nullptr)
2222
{
2323
auto allocator = [&ctx](size_t size) {return (char16*)AnewArray(ctx->allocator, char16, size); };
2424
char16* dst = nullptr;
25-
size_t size;
25+
charcount_t size;
2626
HRESULT hr = utf8::NarrowStringToWide(allocator, src, srcSize ? *srcSize : strlen(src), &dst, &size);
2727
if (hr != S_OK)
2828
{
@@ -86,11 +86,11 @@ Js::Var Int64ToVar(int64 value, void* user_data)
8686
Js::Var StringToVar(const char* src, uint length, void* user_data)
8787
{
8888
Context* ctx = (Context*)user_data;
89-
size_t bufSize = 0;
89+
charcount_t bufSize = 0;
9090
size_t slength = (size_t)length;
9191
char16* buf = NarrowStringToWide(ctx, src, &slength, &bufSize);
9292
Assert(bufSize < UINT32_MAX);
93-
return JavascriptString::NewCopyBuffer(buf, (charcount_t)bufSize, ctx->scriptContext);
93+
return JavascriptString::NewCopyBuffer(buf, bufSize, ctx->scriptContext);
9494
}
9595

9696
Js::Var CreateBuffer(const uint8* buf, uint size, void* user_data)

0 commit comments

Comments
 (0)