Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/path/include/PathAllocCombine.h
Line
Count
Source (jump to first uncovered line)
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/error.h>
26
#include <winpr/wlog.h>
27
28
#if DEFINE_UNICODE
29
30
HRESULT PATH_ALLOC_COMBINE(PCWSTR pszPathIn, PCWSTR pszMore,
31
                           WINPR_ATTR_UNUSED unsigned long dwFlags, PWSTR* ppszPathOut)
32
0
{
33
0
  WLog_WARN("TODO", "has known bugs and needs fixing.");
34
35
0
  if (!ppszPathOut)
36
0
    return E_INVALIDARG;
37
38
0
  if (!pszPathIn && !pszMore)
39
0
    return E_INVALIDARG;
40
41
0
  if (!pszMore)
42
0
    return E_FAIL; /* valid but not implemented, see top comment */
43
44
0
  if (!pszPathIn)
45
0
    return E_FAIL; /* valid but not implemented, see top comment */
46
47
0
  const size_t pszPathInLength = _wcslen(pszPathIn);
48
0
  const size_t pszMoreLength = _wcslen(pszMore);
49
50
  /* prevent segfaults - the complete implementation below is buggy */
51
0
  if (pszPathInLength < 3)
52
0
    return E_FAIL;
53
54
0
  const BOOL backslashIn =
55
0
      (pszPathIn[pszPathInLength - 1] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
56
0
  const BOOL backslashMore = (pszMore[0] == CUR_PATH_SEPARATOR_CHR) ? TRUE : FALSE;
57
58
0
  if (backslashMore)
59
0
  {
60
0
    if ((pszPathIn[1] == ':') && (pszPathIn[2] == CUR_PATH_SEPARATOR_CHR))
61
0
    {
62
0
      const WCHAR colon[] = { ':', '\0' };
63
0
      const size_t pszPathOutLength = sizeof(WCHAR) + pszMoreLength;
64
0
      const size_t sizeOfBuffer = (pszPathOutLength + 1) * sizeof(WCHAR);
65
0
      PWSTR pszPathOut = (PWSTR)calloc(sizeOfBuffer, sizeof(WCHAR));
66
67
0
      if (!pszPathOut)
68
0
        return E_OUTOFMEMORY;
69
70
0
      _wcsncat(pszPathOut, &pszPathIn[0], 1);
71
0
      _wcsncat(pszPathOut, colon, ARRAYSIZE(colon));
72
0
      _wcsncat(pszPathOut, pszMore, pszMoreLength);
73
0
      *ppszPathOut = pszPathOut;
74
0
      return S_OK;
75
0
    }
76
0
  }
77
0
  else
78
0
  {
79
0
    const WCHAR sep[] = CUR_PATH_SEPARATOR_STR;
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, sep, ARRAYSIZE(sep));
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
      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
      sprintf_s(pszPathOut, sizeOfBuffer, "%s%s", pszPathIn, pszMore);
156
0
    else
157
0
      sprintf_s(pszPathOut, sizeOfBuffer, "%s" CUR_PATH_SEPARATOR_STR "%s", pszPathIn,
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
*/