1+ // Copyright (c) Microsoft Corporation. All rights reserved.
2+ // Licensed under the MIT License.
3+
4+ #pragma once
5+
6+ #include < string>
7+
8+ class StringUtils
9+ {
10+ public:
11+
12+ // The maximum string length. Set arbitrarily;
13+ static const size_t MAX_STRING_LEN = 10000 ;
14+
15+ // Gets the length of the given string using the the standard wcsnlen_s.
16+ // Returns E_BOUNDS if the length of wszString is greater than MAX_STRING_LEN.
17+ // For use with untrusted data which may not have a null terminator.
18+ static HRESULT WStringLen (_In_ const WCHAR* wszString, _Out_ size_t & len)
19+ {
20+ len = wcsnlen_s (wszString, MAX_STRING_LEN);
21+
22+ if (len >= MAX_STRING_LEN)
23+ {
24+ return E_BOUNDS;
25+ }
26+
27+ return S_OK;
28+ }
29+
30+ // Gets the length of the given string using the standard strnlen.
31+ // Returns E_BOUNDS if the length of wszString is greater than MAX_STRING_LEN.
32+ // For use with untrusted data which may not have a null terminator.
33+ static HRESULT StringLen (_In_ const char * szString, _Out_ size_t & len)
34+ {
35+ len = strnlen (szString, MAX_STRING_LEN);
36+
37+ if (len >= MAX_STRING_LEN)
38+ {
39+ return E_BOUNDS;
40+ }
41+
42+ return S_OK;
43+ }
44+
45+ // Gets the length of the given string using the standard wcsnlen_s.
46+ // Yields the same result as calling wcsnlen_s(wszString, MAX_STRING_LEN);
47+ // For use with untrusted data which may not have a null terminator.
48+ static size_t WStringLen (_In_ const WCHAR* wszString)
49+ {
50+ return wcsnlen_s (wszString, MAX_STRING_LEN);
51+ }
52+
53+
54+ // Gets the length of the given string using the standard strnlen.
55+ // Yields the same result as calling strnlen(szString, MAX_STRING_LEN);
56+ // For use with untrusted data which may not have a null terminator.
57+ static size_t StringLen (_In_ const char * szString)
58+ {
59+ return strnlen (szString, MAX_STRING_LEN);
60+ }
61+
62+ // Modifies pwszPath by appending pwszMore.
63+ // Checks cBounds before appending to prevent buffer overflows.
64+ //
65+ // This function wraps PathAppend since supporting Win7 means PathCchAppend is not available.
66+ static HRESULT SafePathAppend (_Inout_updates_z_(cBounds) LPWSTR pwszPath, _In_ LPCWSTR pwszMore, _In_ size_t cBounds)
67+ {
68+ #ifndef PLATFORM_UNIX
69+ // If PathAppend fails, the destination buffer will be cleared. Check bounds before appending.
70+ // +1 for additional directory separator character, +1 for null terminator.
71+ if (StringUtils::WStringLen (pwszPath) + StringUtils::WStringLen (pwszMore) + 2 > cBounds)
72+ {
73+ return E_BOUNDS;
74+ }
75+
76+ if (!PathAppend (pwszPath, pwszMore))
77+ {
78+ return E_FAIL;
79+ }
80+
81+ return S_OK;
82+ #else
83+ return PathCchAppend (pwszPath, MAX_PATH, pwszMore);
84+ #endif
85+ }
86+ };
0 commit comments