Coverage Report

Created: 2025-10-10 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/path/include/PathAllocCombine.h
Line
Count
Source
1
2
/*
3
#define DEFINE_UNICODE    FALSE
4
#define CUR_PATH_SEPARATOR_CHR  '\\'
5
#define CUR_PATH_SEPARATOR_STR  "\\"
6
#define PATH_ALLOC_COMBINE  PathAllocCombineA
7
*/
8
9
/**
10
 * FIXME: These implementations of the PathAllocCombine functions have
11
 * several issues:
12
 * - pszPathIn or pszMore may be NULL (but not both)
13
 * - no check if pszMore is fully qualified (if so, it must be directly
14
 *   copied to the output buffer without being combined with pszPathIn.
15
 * - if pszMore begins with a _single_ backslash it must be combined with
16
 *   only the root of the path pointed to by pszPathIn and there's no code
17
 *   to extract the root of pszPathIn.
18
 * - the function will crash with some short string lengths of the parameters
19
 */
20
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include <winpr/wtypes.h>
25
#include <winpr/string.h>
26
#include <winpr/error.h>
27
#include <winpr/wlog.h>
28
29
#if DEFINE_UNICODE
30
31
HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore,
32
                           WINPR_ATTR_UNUSED unsigned long dwFlags, PWSTR* ppszPathOut)
33
0
{
34
0
  WLog_WARN("TODO", "has known bugs and needs fixing.");
35
36
0
  if (!ppszPathOut)
37
0
    return E_INVALIDARG;
38
39
0
  if (!pszPathIn && !pszMore)
40
0
    return E_INVALIDARG;
41
42
0
  if (!pszMore)
43
0
    return E_FAIL; /* valid but not implemented, see top comment */
44
45
0
  if (!pszPathIn)
46
0
    return E_FAIL; /* valid but not implemented, see top comment */
47
48
0
  const size_t pszPathInLength = _wcslen(pszPathIn);
49
0
  const size_t pszMoreLength = _wcslen(pszMore);
50
51
  /* prevent segfaults - the complete implementation below is buggy */
52
0
  if (pszPathInLength < 3)
53
0
    return E_FAIL;
54
55
0
  const BOOL backslashIn =
56
0
      (pszPathIn[pszPathInLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
57
0
  const BOOL backslashMore = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
58
59
0
  if (backslashMore)
60
0
  {
61
0
    if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
62
0
    {
63
0
      const WCHAR colon[] = { ':', '\0' };
64
0
      const size_t pszPathOutLength = sizeof(WCHAR) + pszMoreLength;
65
0
      const size_t sizeOfBuffer = (pszPathOutLength + 1) * sizeof(WCHAR);
66
0
      PWSTR pszPathOut = (PWSTR)calloc(sizeOfBuffer, sizeof(WCHAR));
67
68
0
      if (!pszPathOut)
69
0
        return E_OUTOFMEMORY;
70
71
0
      _wcsncat(pszPathOut, &pszPathIn[0], 1);
72
0
      _wcsncat(pszPathOut, colon, ARRAYSIZE(colon));
73
0
      _wcsncat(pszPathOut, pszMore, pszMoreLength);
74
0
      *ppszPathOut = pszPathOut;
75
0
      return S_OK;
76
0
    }
77
0
  }
78
0
  else
79
0
  {
80
0
    const size_t pszPathOutLength = pszPathInLength + pszMoreLength;
81
0
    const size_t sizeOfBuffer = (pszPathOutLength + 1) * 2;
82
0
    PWSTR pszPathOut = (PWSTR)calloc(sizeOfBuffer, 2);
83
84
0
    if (!pszPathOut)
85
0
      return E_OUTOFMEMORY;
86
87
0
    _wcsncat(pszPathOut, pszPathIn, pszPathInLength);
88
0
    if (!backslashIn)
89
0
      _wcsncat(pszPathOut, CUR_PATH_SEPARATOR_STR, ARRAYSIZE(CUR_PATH_SEPARATOR_STR));
90
0
    _wcsncat(pszPathOut, pszMore, pszMoreLength);
91
92
0
    *ppszPathOut = pszPathOut;
93
0
    return S_OK;
94
0
  }
95
96
0
  return E_FAIL;
97
0
}
Unexecuted instantiation: PathAllocCombineW
Unexecuted instantiation: UnixPathAllocCombineW
Unexecuted instantiation: NativePathAllocCombineW
98
99
#else
100
101
HRESULT PATH_ALLOC_COMBINE(PCSTR pszPathIn, PCSTR pszMore, WINPR_ATTR_UNUSED unsigned long dwFlags,
102
                           PSTR* ppszPathOut)
103
0
{
104
0
  WLog_WARN("TODO", "has known bugs and needs fixing.");
105
106
0
  if (!ppszPathOut)
107
0
    return E_INVALIDARG;
108
109
0
  if (!pszPathIn && !pszMore)
110
0
    return E_INVALIDARG;
111
112
0
  if (!pszMore)
113
0
    return E_FAIL; /* valid but not implemented, see top comment */
114
115
0
  if (!pszPathIn)
116
0
    return E_FAIL; /* valid but not implemented, see top comment */
117
118
0
  const size_t pszPathInLength = strlen(pszPathIn);
119
0
  const size_t pszMoreLength = strlen(pszMore);
120
121
  /* prevent segfaults - the complete implementation below is buggy */
122
0
  if (pszPathInLength < 3)
123
0
    return E_FAIL;
124
125
0
  const BOOL backslashIn =
126
0
      (pszPathIn[pszPathInLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
127
0
  const BOOL backslashMore = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
128
129
0
  if (backslashMore)
130
0
  {
131
0
    if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
132
0
    {
133
0
      const size_t pszPathOutLength = 2 + pszMoreLength;
134
0
      const size_t sizeOfBuffer = (pszPathOutLength + 1) * 2;
135
0
      PSTR pszPathOut = calloc(sizeOfBuffer, 2);
136
137
0
      if (!pszPathOut)
138
0
        return E_OUTOFMEMORY;
139
140
0
      (void)sprintf_s(pszPathOut, sizeOfBuffer, "%c:%s", pszPathIn[0], pszMore);
141
0
      *ppszPathOut = pszPathOut;
142
0
      return S_OK;
143
0
    }
144
0
  }
145
0
  else
146
0
  {
147
0
    const size_t pszPathOutLength = pszPathInLength + pszMoreLength;
148
0
    const size_t sizeOfBuffer = (pszPathOutLength + 1) * 2;
149
0
    PSTR pszPathOut = calloc(sizeOfBuffer, 2);
150
151
0
    if (!pszPathOut)
152
0
      return E_OUTOFMEMORY;
153
154
0
    if (backslashIn)
155
0
      (void)sprintf_s(pszPathOut, sizeOfBuffer, "%s%s", pszPathIn, pszMore);
156
0
    else
157
0
      (void)sprintf_s(pszPathOut, sizeOfBuffer, "%s%s%s", pszPathIn, CUR_PATH_SEPARATOR_STR,
158
0
                      pszMore);
159
160
0
    *ppszPathOut = pszPathOut;
161
0
    return S_OK;
162
0
  }
163
164
0
  return E_FAIL;
165
0
}
Unexecuted instantiation: PathAllocCombineA
Unexecuted instantiation: UnixPathAllocCombineA
Unexecuted instantiation: NativePathAllocCombineA
166
167
#endif
168
169
/*
170
#undef DEFINE_UNICODE
171
#undef CUR_PATH_SEPARATOR_CHR
172
#undef CUR_PATH_SEPARATOR_STR
173
#undef PATH_ALLOC_COMBINE
174
*/