Juan Lang : oleaut32: Correctly handle NULLs embedded in BSTRs,
with tests.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Jun 22 06:17:05 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 2a0c37d8b99f2c1aae3bf988588cac095e78048d
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=2a0c37d8b99f2c1aae3bf988588cac095e78048d
Author: Juan Lang <juan_lang at yahoo.com>
Date: Wed Jun 21 23:56:58 2006 +0200
oleaut32: Correctly handle NULLs embedded in BSTRs, with tests.
---
dlls/oleaut32/tests/vartype.c | 109 ++++++++++++++++++++++++++++++++++++++---
dlls/oleaut32/vartype.c | 29 ++++++++---
2 files changed, 122 insertions(+), 16 deletions(-)
diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c
index 347b256..5e2de4d 100644
--- a/dlls/oleaut32/tests/vartype.c
+++ b/dlls/oleaut32/tests/vartype.c
@@ -4898,8 +4898,8 @@ #undef BSTR_DEC64
#define _VARBSTRCMP(left,right,lcid,flags,result) \
hres = pVarBstrCmp(left,right,lcid,flags); \
ok(hres == result, "VarBstrCmp: expected " #result ", got hres=0x%lx\n", hres)
-#define VARBSTRCMP(left,right,result) \
- _VARBSTRCMP(left,right,lcid,0,result)
+#define VARBSTRCMP(left,right,flags,result) \
+ _VARBSTRCMP(left,right,lcid,flags,result)
static void test_VarBstrCmp(void)
{
@@ -4907,7 +4907,11 @@ static void test_VarBstrCmp(void)
HRESULT hres;
static const WCHAR sz[] = {'W','u','r','s','c','h','t','\0'};
static const WCHAR szempty[] = {'\0'};
- BSTR bstr, bstrempty;
+ static const WCHAR sz1[] = { 'a',0 };
+ static const WCHAR sz2[] = { 'A',0 };
+ static const WCHAR s1[] = { 'a',0 };
+ static const WCHAR s2[] = { 'a',0,'b' };
+ BSTR bstr, bstrempty, bstr2;
CHECKPTR(VarBstrCmp);
@@ -4916,13 +4920,34 @@ static void test_VarBstrCmp(void)
bstrempty = SysAllocString(szempty);
/* NULL handling. Yepp, MSDN is totaly wrong here */
- VARBSTRCMP(NULL,NULL,VARCMP_EQ);
- VARBSTRCMP(bstr,NULL,VARCMP_GT);
- VARBSTRCMP(NULL,bstr,VARCMP_LT);
+ VARBSTRCMP(NULL,NULL,0,VARCMP_EQ);
+ VARBSTRCMP(bstr,NULL,0,VARCMP_GT);
+ VARBSTRCMP(NULL,bstr,0,VARCMP_LT);
/* NULL and empty string comparisions */
- VARBSTRCMP(bstrempty,NULL,VARCMP_EQ);
- VARBSTRCMP(NULL,bstrempty,VARCMP_EQ);
+ VARBSTRCMP(bstrempty,NULL,0,VARCMP_EQ);
+ VARBSTRCMP(NULL,bstrempty,0,VARCMP_EQ);
+
+ SysFreeString(bstr);
+ bstr = SysAllocString(sz1);
+
+ bstr2 = SysAllocString(sz2);
+ VARBSTRCMP(bstr,bstr2,0,VARCMP_LT);
+ VARBSTRCMP(bstr,bstr2,NORM_IGNORECASE,VARCMP_EQ);
+ SysFreeString(bstr2);
+ /* These two strings are considered equal even though one is
+ * NULL-terminated and the other not.
+ */
+ bstr2 = SysAllocStringLen(s1, sizeof(s1) / sizeof(WCHAR));
+ VARBSTRCMP(bstr,bstr2,0,VARCMP_EQ);
+ SysFreeString(bstr2);
+
+ /* These two strings are not equal */
+ bstr2 = SysAllocStringLen(s2, sizeof(s2) / sizeof(WCHAR));
+ VARBSTRCMP(bstr,bstr2,0,VARCMP_LT);
+ SysFreeString(bstr2);
+
+ SysFreeString(bstr);
}
/* Get the internal representation of a BSTR */
@@ -5175,6 +5200,73 @@ static void test_BstrCopy(void)
}
}
+static void test_VarBstrCat(void)
+{
+ static const WCHAR sz1[] = { 'a',0 };
+ static const WCHAR sz2[] = { 'b',0 };
+ static const WCHAR sz1sz2[] = { 'a','b',0 };
+ static const WCHAR s1[] = { 'a',0 };
+ static const WCHAR s2[] = { 'b',0 };
+ static const WCHAR s1s2[] = { 'a',0,'b',0 };
+ HRESULT ret;
+ BSTR str1, str2, res;
+
+ /* Crash
+ ret = VarBstrCat(NULL, NULL, NULL);
+ */
+
+ /* Concatenation of two NULL strings works */
+ ret = VarBstrCat(NULL, NULL, &res);
+ ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
+ ok(res != NULL, "Expected a string\n");
+ ok(SysStringLen(res) == 0, "Expected a 0-length string\n");
+ SysFreeString(res);
+
+ str1 = SysAllocString(sz1);
+
+ /* Concatenation with one NULL arg */
+ ret = VarBstrCat(NULL, str1, &res);
+ ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
+ ok(res != NULL, "Expected a string\n");
+ ok(SysStringLen(res) == SysStringLen(str1), "Unexpected length\n");
+ ok(!memcmp(res, sz1, SysStringLen(str1)), "Unexpected value\n");
+ SysFreeString(res);
+ ret = VarBstrCat(str1, NULL, &res);
+ ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
+ ok(res != NULL, "Expected a string\n");
+ ok(SysStringLen(res) == SysStringLen(str1), "Unexpected length\n");
+ ok(!memcmp(res, sz1, SysStringLen(str1)), "Unexpected value\n");
+ SysFreeString(res);
+
+ /* Concatenation of two zero-terminated strings */
+ str2 = SysAllocString(sz2);
+ ret = VarBstrCat(str1, str2, &res);
+ ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
+ ok(res != NULL, "Expected a string\n");
+ ok(SysStringLen(res) == sizeof(sz1sz2) / sizeof(WCHAR) - 1,
+ "Unexpected length\n");
+ ok(!memcmp(res, sz1sz2, sizeof(sz1sz2)), "Unexpected value\n");
+ SysFreeString(res);
+
+ SysFreeString(str2);
+ SysFreeString(str1);
+
+ /* Concatenation of two strings with embedded NULLs */
+ str1 = SysAllocStringLen(s1, sizeof(s1) / sizeof(WCHAR));
+ str2 = SysAllocStringLen(s2, sizeof(s2) / sizeof(WCHAR));
+
+ ret = VarBstrCat(str1, str2, &res);
+ ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
+ ok(res != NULL, "Expected a string\n");
+ ok(SysStringLen(res) == sizeof(s1s2) / sizeof(WCHAR),
+ "Unexpected length\n");
+ ok(!memcmp(res, s1s2, sizeof(s1s2)), "Unexpected value\n");
+ SysFreeString(res);
+
+ SysFreeString(str2);
+ SysFreeString(str1);
+}
+
/* IUnknown */
static void test_IUnknownClear(void)
@@ -5940,6 +6032,7 @@ START_TEST(vartype)
test_SysReAllocString();
test_SysReAllocStringLen();
test_BstrCopy();
+ test_VarBstrCat();
test_IUnknownClear();
test_IUnknownCopy();
diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c
index e08a7c0..519c9e0 100644
--- a/dlls/oleaut32/vartype.c
+++ b/dlls/oleaut32/vartype.c
@@ -6584,27 +6584,31 @@ HRESULT WINAPI VarBstrFromDisp(IDispatch
*/
HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
{
- unsigned int len;
+ unsigned int lenLeft, lenRight;
+
+ TRACE("%s,%s,%p\n",
+ debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
+ debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
if (!pbstrOut)
return E_INVALIDARG;
- len = pbstrLeft ? strlenW(pbstrLeft) : 0;
- if (pbstrRight)
- len += strlenW(pbstrRight);
+ lenLeft = pbstrLeft ? SysStringLen(pbstrLeft) : 0;
+ lenRight = pbstrRight ? SysStringLen(pbstrRight) : 0;
- *pbstrOut = SysAllocStringLen(NULL, len);
+ *pbstrOut = SysAllocStringLen(NULL, lenLeft + lenRight);
if (!*pbstrOut)
return E_OUTOFMEMORY;
(*pbstrOut)[0] = '\0';
if (pbstrLeft)
- strcpyW(*pbstrOut, pbstrLeft);
+ memcpy(*pbstrOut, pbstrLeft, lenLeft * sizeof(WCHAR));
if (pbstrRight)
- strcatW(*pbstrOut, pbstrRight);
+ memcpy(*pbstrOut + lenLeft, pbstrRight, lenRight * sizeof(WCHAR));
+ TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
return S_OK;
}
@@ -6629,6 +6633,12 @@ HRESULT WINAPI VarBstrCat(BSTR pbstrLeft
*/
HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
{
+ HRESULT hres;
+
+ TRACE("%s,%s,%ld,%08lx\n",
+ debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
+ debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
+
if (!pbstrLeft || !*pbstrLeft)
{
if (!pbstrRight || !*pbstrRight)
@@ -6638,7 +6648,10 @@ HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft
else if (!pbstrRight || !*pbstrRight)
return VARCMP_GT;
- return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1;
+ hres = CompareStringW(lcid, dwFlags, pbstrLeft, SysStringLen(pbstrLeft),
+ pbstrRight, SysStringLen(pbstrRight)) - 1;
+ TRACE("%ld\n", hres);
+ return hres;
}
/*
More information about the wine-cvs
mailing list