Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/utils/print.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Print Utils
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <winpr/config.h>
21
#include <winpr/debug.h>
22
23
#include <stdio.h>
24
#include <string.h>
25
#include <stdarg.h>
26
#include <errno.h>
27
28
#include <winpr/crt.h>
29
#include <winpr/print.h>
30
31
#include "../log.h"
32
33
#ifndef MIN
34
0
#define MIN(a, b) (a) < (b) ? (a) : (b)
35
#endif
36
37
void winpr_HexDump(const char* tag, UINT32 level, const void* data, size_t length)
38
0
{
39
0
  wLog* log = WLog_Get(tag);
40
0
  winpr_HexLogDump(log, level, data, length);
41
0
}
42
43
void winpr_HexLogDump(wLog* log, UINT32 level, const void* data, size_t length)
44
0
{
45
0
  const BYTE* p = data;
46
0
  size_t line = 0;
47
0
  size_t offset = 0;
48
0
  const size_t maxlen = 20; /* 64bit SIZE_MAX as decimal */
49
  /* String line length:
50
   * prefix          '[1234] '
51
   * hexdump         '01 02 03 04'
52
   * separator       '   '
53
   * ASIC line       'ab..cd'
54
   * zero terminator '\0'
55
   */
56
0
  const size_t blen = (maxlen + 3ULL) + (WINPR_HEXDUMP_LINE_LENGTH * 3ULL) + 3ULL +
57
0
                      WINPR_HEXDUMP_LINE_LENGTH + 1ULL;
58
0
  size_t pos = 0;
59
60
0
  char* buffer = NULL;
61
62
0
  if (!WLog_IsLevelActive(log, level))
63
0
    return;
64
65
0
  if (!log)
66
0
    return;
67
68
0
  buffer = malloc(blen);
69
70
0
  if (!buffer)
71
0
  {
72
0
    char ebuffer[256] = { 0 };
73
0
    WLog_Print(log, WLOG_ERROR, "malloc(%" PRIuz ") failed with [%" PRIuz "] %s", blen, errno,
74
0
               winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
75
0
    return;
76
0
  }
77
78
0
  while (offset < length)
79
0
  {
80
0
    int rc = _snprintf(&buffer[pos], blen - pos, "%04" PRIuz " ", offset);
81
82
0
    if (rc < 0)
83
0
      goto fail;
84
85
0
    pos += (size_t)rc;
86
0
    line = length - offset;
87
88
0
    if (line > WINPR_HEXDUMP_LINE_LENGTH)
89
0
      line = WINPR_HEXDUMP_LINE_LENGTH;
90
91
0
    size_t i = 0;
92
0
    for (; i < line; i++)
93
0
    {
94
0
      rc = _snprintf(&buffer[pos], blen - pos, "%02" PRIx8 " ", p[i]);
95
96
0
      if (rc < 0)
97
0
        goto fail;
98
99
0
      pos += (size_t)rc;
100
0
    }
101
102
0
    for (; i < WINPR_HEXDUMP_LINE_LENGTH; i++)
103
0
    {
104
0
      rc = _snprintf(&buffer[pos], blen - pos, "   ");
105
106
0
      if (rc < 0)
107
0
        goto fail;
108
109
0
      pos += (size_t)rc;
110
0
    }
111
112
0
    for (size_t j = 0; j < line; j++)
113
0
    {
114
0
      rc = _snprintf(&buffer[pos], blen - pos, "%c",
115
0
                     (p[j] >= 0x20 && p[j] < 0x7F) ? (char)p[j] : '.');
116
117
0
      if (rc < 0)
118
0
        goto fail;
119
120
0
      pos += (size_t)rc;
121
0
    }
122
123
0
    WLog_Print(log, level, "%s", buffer);
124
0
    offset += line;
125
0
    p += line;
126
0
    pos = 0;
127
0
  }
128
129
0
  WLog_Print(log, level, "[length=%" PRIuz "] ", length);
130
0
fail:
131
0
  free(buffer);
132
0
}
133
134
void winpr_CArrayDump(const char* tag, UINT32 level, const void* data, size_t length, size_t width)
135
0
{
136
0
  const BYTE* p = data;
137
0
  size_t offset = 0;
138
0
  const size_t llen = ((length > width) ? width : length) * 4ull + 1ull;
139
0
  size_t pos = 0;
140
0
  char* buffer = malloc(llen);
141
142
0
  if (!buffer)
143
0
  {
144
0
    char ebuffer[256] = { 0 };
145
0
    WLog_ERR(tag, "malloc(%" PRIuz ") failed with [%d] %s", llen, errno,
146
0
             winpr_strerror(errno, ebuffer, sizeof(ebuffer)));
147
0
    return;
148
0
  }
149
150
0
  while (offset < length)
151
0
  {
152
0
    size_t line = length - offset;
153
154
0
    if (line > width)
155
0
      line = width;
156
157
0
    pos = 0;
158
159
0
    for (size_t i = 0; i < line; i++)
160
0
    {
161
0
      const int rc = _snprintf(&buffer[pos], llen - pos, "\\x%02" PRIX8 "", p[i]);
162
0
      if (rc < 0)
163
0
        goto fail;
164
0
      pos += (size_t)rc;
165
0
    }
166
167
0
    WLog_LVL(tag, level, "%s", buffer);
168
0
    offset += line;
169
0
    p += line;
170
0
  }
171
172
0
fail:
173
0
  free(buffer);
174
0
}
175
176
static BYTE value(char c)
177
0
{
178
0
  if ((c >= '0') && (c <= '9'))
179
0
    return (c - '0') & 0xFF;
180
0
  if ((c >= 'A') && (c <= 'F'))
181
0
    return (10 + c - 'A') & 0xFF;
182
0
  if ((c >= 'a') && (c <= 'f'))
183
0
    return (10 + c - 'a') & 0xFF;
184
0
  return 0;
185
0
}
186
187
size_t winpr_HexStringToBinBuffer(const char* str, size_t strLength, BYTE* data, size_t dataLength)
188
0
{
189
0
  size_t y = 0;
190
0
  size_t maxStrLen = 0;
191
0
  if (!str || !data || (strLength == 0) || (dataLength == 0))
192
0
    return 0;
193
194
0
  maxStrLen = strnlen(str, strLength);
195
0
  for (size_t x = 0; x < maxStrLen;)
196
0
  {
197
0
    BYTE val = value(str[x++]);
198
0
    if (x < maxStrLen)
199
0
      val = (BYTE)(val << 4) | (value(str[x++]));
200
0
    if (x < maxStrLen)
201
0
    {
202
0
      if (str[x] == ' ')
203
0
        x++;
204
0
    }
205
0
    data[y++] = val;
206
0
    if (y >= dataLength)
207
0
      return y;
208
0
  }
209
0
  return y;
210
0
}
211
212
size_t winpr_BinToHexStringBuffer(const BYTE* data, size_t length, char* dstStr, size_t dstSize,
213
                                  BOOL space)
214
0
{
215
0
  const size_t n = space ? 3 : 2;
216
0
  const char bin2hex[] = "0123456789ABCDEF";
217
0
  const size_t maxLength = MIN(length, dstSize / n);
218
219
0
  if (!data || !dstStr || (length == 0) || (dstSize == 0))
220
0
    return 0;
221
222
0
  for (size_t i = 0; i < maxLength; i++)
223
0
  {
224
0
    const int ln = data[i] & 0xF;
225
0
    const int hn = (data[i] >> 4) & 0xF;
226
0
    char* dst = &dstStr[i * n];
227
228
0
    dst[0] = bin2hex[hn];
229
0
    dst[1] = bin2hex[ln];
230
231
0
    if (space)
232
0
      dst[2] = ' ';
233
0
  }
234
235
0
  if (space && (maxLength > 0))
236
0
  {
237
0
    dstStr[maxLength * n - 1] = '\0';
238
0
    return maxLength * n - 1;
239
0
  }
240
0
  dstStr[maxLength * n] = '\0';
241
0
  return maxLength * n;
242
0
}
243
244
char* winpr_BinToHexString(const BYTE* data, size_t length, BOOL space)
245
0
{
246
0
  size_t rc = 0;
247
0
  const size_t n = space ? 3 : 2;
248
0
  const size_t size = (length + 1ULL) * n;
249
0
  char* p = (char*)malloc(size);
250
251
0
  if (!p)
252
0
    return NULL;
253
254
0
  rc = winpr_BinToHexStringBuffer(data, length, p, size, space);
255
0
  if (rc == 0)
256
0
  {
257
0
    free(p);
258
0
    return NULL;
259
0
  }
260
261
0
  return p;
262
0
}