[DDK] RtlUnicodeStringPrintf(Ex) implementations and ntstrsafe.h tests (#522, #523)

[KMTESTS:RTL] (CORE-14565)

+ Added buffer overrun tests.
+ New style header.
+ ISO C90 compatibility

[DDK] (CORE-9819): RtlUnicodeStringPrintf(Ex) and RtlUnicodeStringValidate(Ex) fixes plus formatting.

[DDK]: Cosmetic changes  (NTSTATUS variable naming and tabs)

[DDK] First implementation of Unicode functions for NtStrSafe (CORE-9819)

+ This implementation does not modify the interface of previous functions.
+ Since we need length returned for the destination UNICODE_STRING.Length field:
  - an intermediate "Len" postfixed function was added with optional
    argument to return the _vsnwprintf character count.
  - Wide Printf(Ex) functions already existent work now call new Rtlp
    private worker functions.
+ For several UnicodeStringPrintf(Ex) tests, see work going on CORE-14565

NOTES:

+ MSDN says they won't insert NULL characters on formatted strings. But
  seems this is incorrect at MSDN (interpret this as DONT ASSUME NULL-termination).
  We return zero-terminated strings, and MS functions seems to do the same.
  (XP DDK 7.1)

[DDK] First implementation of Unicode functions for NtStrSafe (CORE-9819)

+ This implementation does not modify the interface of previous functions.
+ Since we need length returned for the destination UNICODE_STRING.Length field:
  - an intermediate "Len" postfixed function was added with optional
    argument to return the _vsnwprintf character count.
  - Wide Printf(Ex) functions already existent work now call new Rtlp
    private worker functions.
+ For several UnicodeStringPrintf(Ex) tests, see work going on CORE-14565

NOTES:

+ MSDN says they won't insert NULL characters on formatted strings. But
  seems this is incorrect at MSDN (interpret this as DONT ASSUME NULL-termination).
  We return zero-terminated strings, and MS functions seems to do the same.
  (XP DDK 7.1)

[DDK] Fixed bad NtStrSafe.h va_start call (CORE-9819)

Update on RtlUnicodeStringPrintfEx plus cosmetic changes.

[DDK] First implementation of Unicode functions for NtStrSafe (CORE-9819)

+ This implementation does not modify the interface of previous functions.
+ Since we need length returned for the destination UNICODE_STRING.Length field:
  - an intermediate "Len" postfixed function was added with optional
    argument to return the _vsnwprintf character count.
  - Wide Printf(Ex) functions already existent work now call new Rtlp
    private worker functions.
+ For several UnicodeStringPrintf(Ex) tests, see work going on CORE-14565

NOTES:

+ MSDN says they won't insert NULL characters on formatted strings. But
  seems this is incorrect at MSDN (interpret this as DONT ASSUME NULL-termination).
  We return zero-terminated strings, and MS functions seems to do the same.
  (XP DDK 7.1)

[KMTESTS:RTL] Tests for new RtlUnicodePrintf(Ex) functions (CORE-14565)

+ 45 Tests working.
+ Lacks remaining non-Unicode functions in NtStrSafe.h for now.
+ Used for first tests on CORE-9819

[KMTESTS/RTL] Fixed test not taking care of null (CORE-14565)

[DDK] Fixed bad NtStrSafe.h va_start call (CORE-9819)

[KMTESTS:RTL] First Test.

Update on RtlUnicodeStringPrintfEx plus cosmetic changes.

[KMTESTS] Added NtStrSafe to test lists (CORE-14565)

First commit: Skeleton for test implementation + Addition to COMMON SOURCES in kmtests Cmake lists.

WIP.
+Implementation of RtlStringVPrintfWorkerLenW, RtlStringVPrintfExWorkerLenW to avoid changing existing public functions. This is required as existent functions did not return vsnprintf result, so we didn't have any return info to update UNICODE_STRING.Length.
+Additional implementation of RtlUnicodeStringValidate for checking purposes.
+Former RtlStringVPrintfWorker(ex) refactored to RtlInternalStringVPrintf(Ex)WorkerW.
+No ANSI functions affected as we didn't need them for Unicode printf's.

WIP: RtlUnicodeStringPrintf
This commit is contained in:
Hernán Di Pietro 2018-04-21 08:56:12 +02:00 committed by Colin Finck
parent 162e43d927
commit 99818568ed
No known key found for this signature in database
GPG key ID: 1BA74E70456BA1A9
5 changed files with 493 additions and 37 deletions

View file

@ -23,6 +23,7 @@ list(APPEND COMMON_SOURCE
rtl/RtlRegistry.c
rtl/RtlSplayTree.c
rtl/RtlStack.c
rtl/RtlStrSafe.c
rtl/RtlUnicodeString.c)
#

View file

@ -31,6 +31,7 @@ KMT_TESTFUNC Test_RtlMemory;
KMT_TESTFUNC Test_RtlRegistry;
KMT_TESTFUNC Test_RtlSplayTree;
KMT_TESTFUNC Test_RtlStack;
KMT_TESTFUNC Test_RtlStrSafe;
KMT_TESTFUNC Test_RtlUnicodeString;
KMT_TESTFUNC Test_TcpIpIoctl;
KMT_TESTFUNC Test_TcpIpTdi;
@ -64,6 +65,7 @@ const KMT_TEST TestList[] =
{ "RtlRegistry", Test_RtlRegistry },
{ "RtlSplayTree", Test_RtlSplayTree },
{ "RtlStack", Test_RtlStack },
{ "RtlStrSafe", Test_RtlStrSafe },
{ "RtlUnicodeString", Test_RtlUnicodeString },
{ "TcpIpTdi", Test_TcpIpTdi },
{ "TcpIpConnect", Test_TcpIpConnect },

View file

@ -72,6 +72,7 @@ KMT_TESTFUNC Test_RtlMemory;
KMT_TESTFUNC Test_RtlRegistry;
KMT_TESTFUNC Test_RtlSplayTree;
KMT_TESTFUNC Test_RtlStack;
KMT_TESTFUNC Test_RtlStrSafe;
KMT_TESTFUNC Test_RtlUnicodeString;
KMT_TESTFUNC Test_ZwAllocateVirtualMemory;
KMT_TESTFUNC Test_ZwCreateSection;
@ -144,6 +145,7 @@ const KMT_TEST TestList[] =
{ "RtlRegistryKM", Test_RtlRegistry },
{ "RtlSplayTreeKM", Test_RtlSplayTree },
{ "RtlStackKM", Test_RtlStack },
{ "RtlStrSafeKM", Test_RtlStrSafe },
{ "RtlUnicodeStringKM", Test_RtlUnicodeString },
{ "SeInheritance", Test_SeInheritance },
{ "SeQueryInfoToken", Test_SeQueryInfoToken },

View file

@ -0,0 +1,179 @@
/*
* PROJECT: ReactOS kernel-mode tests
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Test for ntstrsafe.h functions
* COPYRIGHT: Copyright 2018 Hernán Di Pietro <hernan.di.pietro@gmail.com>
*/
#define KMT_EMULATE_KERNEL
#include <kmt_test.h>
#include <ntstrsafe.h>
#include <ntdef.h>
#include <ndk/rtlfuncs.h>
#define TESTAPI static void
TESTAPI
Test_RtlUnicodeStringPrintf()
{
WCHAR Buffer[1024];
WCHAR OvrBuffer[1024];
WCHAR BufferSmall[2];
WCHAR BufferSmall2[7];
UNICODE_STRING UsString;
const WCHAR FormatStringInts[] = L"%d %d %d";
const WCHAR FormatStringStrs[] = L"%s %s %s";
const WCHAR Result[] = L"1 2 3";
UNICODE_STRING UsStringNull;
/* No zeros (Don't assume UNICODE_STRINGS are NULL terminated) */
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
RtlFillMemory(BufferSmall, sizeof(BufferSmall), 0xAA);
RtlFillMemory(BufferSmall2, sizeof(BufferSmall2), 0xAA);
/* STATUS_SUCCESS test */
UsString.Buffer = Buffer;
UsString.Length = 0;
UsString.MaximumLength = sizeof(Buffer);
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringInts, 1, 2, 3), STATUS_SUCCESS);
ok_eq_uint(UsString.Length, sizeof(Result) - sizeof(WCHAR));
ok_eq_uint(UsString.MaximumLength, sizeof(Buffer));
ok_eq_wchar(UsString.Buffer[0], L'1');
ok_eq_wchar(UsString.Buffer[1], L' ');
ok_eq_wchar(UsString.Buffer[2], L'2');
ok_eq_wchar(UsString.Buffer[3], L' ');
ok_eq_wchar(UsString.Buffer[4], L'3');
ok_eq_wchar(UsString.Buffer[5], (WCHAR) 0);
/* STATUS_BUFFER_OVERFLOW tests */
UsString.Buffer = BufferSmall;
UsString.Length = 0;
UsString.MaximumLength = sizeof(BufferSmall);
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW);
ok_eq_uint(UsString.Length, UsString.MaximumLength);
ok_eq_char(UsString.Buffer[0], L'A');
ok_eq_char(UsString.Buffer[1], (WCHAR)0);
UsString.Buffer = BufferSmall2;
UsString.Length = 0;
UsString.MaximumLength = sizeof(BufferSmall2);
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"0123", L"4567", L"89AB"), STATUS_BUFFER_OVERFLOW);
ok_eq_uint(UsString.Length, UsString.MaximumLength);
ok_eq_char(UsString.Buffer[0], L'0');
ok_eq_char(UsString.Buffer[1], L'1');
ok_eq_char(UsString.Buffer[2], L'2');
ok_eq_char(UsString.Buffer[3], L'3');
ok_eq_char(UsString.Buffer[4], L' ');
ok_eq_char(UsString.Buffer[5], L'4');
ok_eq_char(UsString.Buffer[6], (WCHAR) 0);
///* STATUS_INVALID_PARAMETER tests */
ok_eq_hex(RtlUnicodeStringPrintf(NULL, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, NULL, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
UsStringNull.Buffer = (PWCH)NULL;
UsStringNull.Length = 0;
UsStringNull.MaximumLength = 0;
ok_eq_bool(RtlUnicodeStringPrintf(&UsStringNull, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_INVALID_PARAMETER);
/* Test for buffer overruns */
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
RtlFillMemory(OvrBuffer, sizeof(OvrBuffer), 0xAA);
UsString.Buffer = Buffer;
UsString.Length = 0;
UsString.MaximumLength = 16 * sizeof(WCHAR);
ok_eq_hex(RtlUnicodeStringPrintf(&UsString, FormatStringStrs, L"abc", L"def", L"ghi"), STATUS_SUCCESS);
ok_eq_uint(UsString.Length, sizeof(L"abc def ghi") -sizeof(WCHAR));
ok_eq_char(UsString.Buffer[11], (WCHAR)0);
ok_eq_uint(0, memcmp(OvrBuffer + 12, Buffer + 12, sizeof(Buffer) - (12 * sizeof(WCHAR))));
}
TESTAPI
Test_RtlUnicodeStringPrintfEx()
{
WCHAR Buffer[32];
WCHAR BufferSmall[8] = { 0 };
WCHAR OvrBuffer[1024];
UNICODE_STRING UsString, RemString;
const WCHAR FormatStringInts[] = L"%d %d %d";
const WCHAR FormatStringStrs[] = L"%s %s %s";
const WCHAR Result[] = L"1 2 3";
/* No zeros (Don't assume UNICODE_STRINGS are NULL terminated) */
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
UsString.Buffer = Buffer;
UsString.Length = 0;
UsString.MaximumLength = sizeof(Buffer);
RemString.Buffer = (PWCH)NULL;
RemString.Length = 0;
RemString.MaximumLength = 0;
/* STATUS_SUCCESS test, fill behind flag: low-byte as fill character */
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, STRSAFE_FILL_BEHIND | 0xFF, FormatStringInts, 1, 2, 3), STATUS_SUCCESS);
ok_eq_uint(UsString.Length, sizeof(Result) - sizeof(WCHAR));
ok_eq_uint(UsString.MaximumLength, sizeof(Buffer));
ok_eq_uint(memcmp(UsString.Buffer, Result, sizeof(Result) - sizeof(WCHAR)), 0);
ok_eq_pointer(RemString.Buffer, UsString.Buffer + (UsString.Length / sizeof(WCHAR)));
ok_eq_uint(RemString.Length, 0);
ok_eq_uint(RemString.MaximumLength, UsString.MaximumLength - UsString.Length);
/* STATUS_BUFFER_OVERFLOW test */
UsString.Buffer = BufferSmall;
UsString.Length = 0;
UsString.MaximumLength = sizeof(BufferSmall);
RemString.Buffer = (PWCH)NULL;
RemString.Length = 0;
RemString.MaximumLength = 0;
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"AAA", L"BBB", L"CCC"), STATUS_BUFFER_OVERFLOW);
ok_eq_uint(UsString.Length, UsString.MaximumLength);
ok_eq_char(UsString.Buffer[0], L'A');
ok_eq_char(UsString.Buffer[1], L'A');
ok_eq_char(UsString.Buffer[2], L'A');
ok_eq_char(UsString.Buffer[3], L' ');
ok_eq_char(UsString.Buffer[4], L'B');
ok_eq_char(UsString.Buffer[5], L'B');
ok_eq_char(UsString.Buffer[6], L'B');
ok_eq_char(UsString.Buffer[7], (WCHAR)0);
// Takes \0 into account
ok_eq_pointer(RemString.Buffer, UsString.Buffer + (UsString.Length - 1) / sizeof(WCHAR));
ok_eq_uint(RemString.Length, 0);
ok_eq_uint(RemString.MaximumLength, 2);
/* Test for buffer overruns */
RtlFillMemory(Buffer, sizeof(Buffer), 0xAA);
RtlFillMemory(OvrBuffer, sizeof(OvrBuffer), 0xAA);
UsString.Buffer = Buffer;
UsString.Length = 0;
UsString.MaximumLength = 16 * sizeof(WCHAR);
ok_eq_hex(RtlUnicodeStringPrintfEx(&UsString, &RemString, 0, FormatStringStrs, L"abc", L"def", L"ghi"), STATUS_SUCCESS);
ok_eq_uint(UsString.Length, sizeof(L"abc def ghi") - sizeof(WCHAR));
ok_eq_char(UsString.Buffer[11], (WCHAR)0);
ok_eq_uint(0, memcmp(OvrBuffer + 12, Buffer + 12, sizeof(Buffer) - (12 * sizeof(WCHAR))));
}
START_TEST(RtlStrSafe)
{
Test_RtlUnicodeStringPrintf();
Test_RtlUnicodeStringPrintfEx();
}