Coverage Report

Created: 2023-09-25 06:56

/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
22
#include <stdio.h>
23
#include <string.h>
24
#include <stdarg.h>
25
#include <errno.h>
26
27
#include <winpr/crt.h>
28
#include <winpr/print.h>
29
30
#include "../log.h"
31
32
#ifndef MIN
33
53
#define MIN(a, b) (a) < (b) ? (a) : (b)
34
#endif
35
36
void winpr_HexDump(const char* tag, UINT32 level, const void* data, size_t length)
37
0
{
38
0
  wLog* log = WLog_Get(tag);
39
0
  winpr_HexLogDump(log, level, data, length);
40
0
}
41
42
void winpr_HexLogDump(wLog* log, UINT32 lvl, const void* data, size_t length)
43
0
{
44
0
  const BYTE* p = data;
45
0
  size_t i, line, offset = 0;
46
0
  const size_t maxlen = 20; /* 64bit SIZE_MAX as decimal */
47
  /* String line length:
48
   * prefix          '[1234] '
49
   * hexdump         '01 02 03 04'
50
   * separator       '   '
51
   * ASIC line       'ab..cd'
52
   * zero terminator '\0'
53
   */
54
0
  const size_t blen =
55
0
      (maxlen + 3) + (WINPR_HEXDUMP_LINE_LENGTH * 3) + 3 + WINPR_HEXDUMP_LINE_LENGTH + 1;
56
0
  size_t pos = 0;
57
58
0
  char* buffer;
59
60
0
  if (!WLog_IsLevelActive(log, lvl))
61
0
    return;
62
63
0
  if (!log)
64
0
    return;
65
66
0
  buffer = malloc(blen);
67
68
0
  if (!buffer)
69
0
  {
70
0
    WLog_Print(log, WLOG_ERROR, "malloc(%" PRIuz ") failed with [%" PRIuz "] %s", blen, errno,
71
0
               strerror(errno));
72
0
    return;
73
0
  }
74
75
0
  while (offset < length)
76
0
  {
77
0
    int rc = _snprintf(&buffer[pos], blen - pos, "%04" PRIuz " ", offset);
78
79
0
    if (rc < 0)
80
0
      goto fail;
81
82
0
    pos += (size_t)rc;
83
0
    line = length - offset;
84
85
0
    if (line > WINPR_HEXDUMP_LINE_LENGTH)
86
0
      line = WINPR_HEXDUMP_LINE_LENGTH;
87
88
0
    for (i = 0; i < line; i++)
89
0
    {
90
0
      rc = _snprintf(&buffer[pos], blen - pos, "%02" PRIx8 " ", p[i]);
91
92
0
      if (rc < 0)
93
0
        goto fail;
94
95
0
      pos += (size_t)rc;
96
0
    }
97
98
0
    for (; i < WINPR_HEXDUMP_LINE_LENGTH; i++)
99
0
    {
100
0
      rc = _snprintf(&buffer[pos], blen - pos, "   ");
101
102
0
      if (rc < 0)
103
0
        goto fail;
104
105
0
      pos += (size_t)rc;
106
0
    }
107
108
0
    for (i = 0; i < line; i++)
109
0
    {
110
0
      rc = _snprintf(&buffer[pos], blen - pos, "%c",
111
0
                     (p[i] >= 0x20 && p[i] < 0x7F) ? (char)p[i] : '.');
112
113
0
      if (rc < 0)
114
0
        goto fail;
115
116
0
      pos += (size_t)rc;
117
0
    }
118
119
0
    WLog_Print(log, lvl, "%s", buffer);
120
0
    offset += line;
121
0
    p += line;
122
0
    pos = 0;
123
0
  }
124
125
0
  WLog_Print(log, lvl, "[length=%" PRIuz "] ", length);
126
0
fail:
127
0
  free(buffer);
128
0
}
129
130
void winpr_CArrayDump(const char* tag, UINT32 level, const void* data, size_t length, size_t width)
131
0
{
132
0
  const BYTE* p = data;
133
0
  size_t i, offset = 0;
134
0
  const size_t llen = ((length > width) ? width : length) * 4ull + 1ull;
135
0
  size_t pos;
136
0
  char* buffer = malloc(llen);
137
138
0
  if (!buffer)
139
0
  {
140
0
    WLog_ERR(tag, "malloc(%" PRIuz ") failed with [%d] %s", llen, errno, strerror(errno));
141
0
    return;
142
0
  }
143
144
0
  while (offset < length)
145
0
  {
146
0
    size_t line = length - offset;
147
148
0
    if (line > width)
149
0
      line = width;
150
151
0
    pos = 0;
152
153
0
    for (i = 0; i < line; i++)
154
0
    {
155
0
      const int rc = _snprintf(&buffer[pos], llen - pos, "\\x%02" PRIX8 "", p[i]);
156
0
      if (rc < 0)
157
0
        goto fail;
158
0
      pos += (size_t)rc;
159
0
    }
160
161
0
    WLog_LVL(tag, level, "%s", buffer);
162
0
    offset += line;
163
0
    p += line;
164
0
  }
165
166
0
fail:
167
0
  free(buffer);
168
0
}
169
170
static BYTE value(char c)
171
0
{
172
0
  if ((c >= '0') && (c <= '9'))
173
0
    return c - '0';
174
0
  if ((c >= 'A') && (c <= 'F'))
175
0
    return 10 + c - 'A';
176
0
  if ((c >= 'a') && (c <= 'f'))
177
0
    return 10 + c - 'a';
178
0
  return 0;
179
0
}
180
181
size_t winpr_HexStringToBinBuffer(const char* str, size_t strLength, BYTE* data, size_t dataLength)
182
0
{
183
0
  size_t x, y = 0;
184
0
  size_t maxStrLen;
185
0
  if (!str || !data || (strLength == 0) || (dataLength == 0))
186
0
    return 0;
187
188
0
  maxStrLen = strnlen(str, strLength);
189
0
  for (x = 0; x < maxStrLen;)
190
0
  {
191
0
    BYTE val = value(str[x++]);
192
0
    if (x < maxStrLen)
193
0
      val = (BYTE)(val << 4) | (value(str[x++]));
194
0
    if (x < maxStrLen)
195
0
    {
196
0
      if (str[x] == ' ')
197
0
        x++;
198
0
    }
199
0
    data[y++] = val;
200
0
    if (y >= dataLength)
201
0
      return y;
202
0
  }
203
0
  return y;
204
0
}
205
206
size_t winpr_BinToHexStringBuffer(const BYTE* data, size_t length, char* dstStr, size_t dstSize,
207
                                  BOOL space)
208
53
{
209
53
  const size_t n = space ? 3 : 2;
210
53
  const char bin2hex[] = "0123456789ABCDEF";
211
53
  const size_t maxLength = MIN(length, dstSize / n);
212
53
  size_t i;
213
214
53
  if (!data || !dstStr || (length == 0) || (dstSize == 0))
215
0
    return 0;
216
217
8.38M
  for (i = 0; i < maxLength; i++)
218
8.38M
  {
219
8.38M
    const int ln = data[i] & 0xF;
220
8.38M
    const int hn = (data[i] >> 4) & 0xF;
221
8.38M
    char* dst = &dstStr[i * n];
222
223
8.38M
    dst[0] = bin2hex[hn];
224
8.38M
    dst[1] = bin2hex[ln];
225
226
8.38M
    if (space)
227
0
      dst[2] = ' ';
228
8.38M
  }
229
230
53
  if (space && (maxLength > 0))
231
0
  {
232
0
    dstStr[maxLength * n - 1] = '\0';
233
0
    return maxLength * n - 1;
234
0
  }
235
53
  dstStr[maxLength * n] = '\0';
236
53
  return maxLength * n;
237
53
}
238
239
char* winpr_BinToHexString(const BYTE* data, size_t length, BOOL space)
240
53
{
241
53
  size_t rc;
242
53
  const size_t n = space ? 3 : 2;
243
53
  const size_t size = (length + 1ULL) * n;
244
53
  char* p = (char*)malloc(size);
245
246
53
  if (!p)
247
0
    return NULL;
248
249
53
  rc = winpr_BinToHexStringBuffer(data, length, p, size, space);
250
53
  if (rc == 0)
251
0
  {
252
0
    free(p);
253
0
    return NULL;
254
0
  }
255
256
53
  return p;
257
53
}