Coverage Report

Created: 2025-11-09 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/yara/libyara/strutils.c
Line
Count
Source
1
/*
2
Copyright (c) 2007-2014. The YARA Authors. All Rights Reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
1. Redistributions of source code must retain the above copyright notice, this
8
list of conditions and the following disclaimer.
9
10
2. Redistributions in binary form must reproduce the above copyright notice,
11
this list of conditions and the following disclaimer in the documentation and/or
12
other materials provided with the distribution.
13
14
3. Neither the name of the copyright holder nor the names of its contributors
15
may be used to endorse or promote products derived from this software without
16
specific prior written permission.
17
18
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <stdio.h>
31
#include <string.h>
32
#include <yara/mem.h>
33
#include <yara/strutils.h>
34
35
uint64_t xtoi(const char* hexstr)
36
65.3k
{
37
65.3k
  size_t i;
38
65.3k
  size_t l = strlen(hexstr);
39
40
65.3k
  uint64_t r = 0;
41
42
195k
  for (i = 0; i < l; i++)
43
130k
  {
44
130k
    switch (hexstr[i])
45
130k
    {
46
9.90k
    case '0':
47
12.0k
    case '1':
48
12.8k
    case '2':
49
13.8k
    case '3':
50
14.3k
    case '4':
51
15.8k
    case '5':
52
16.9k
    case '6':
53
17.1k
    case '7':
54
17.6k
    case '8':
55
17.7k
    case '9':
56
17.7k
      r |= ((uint64_t) (hexstr[i] - '0')) << ((l - i - 1) * 4);
57
17.7k
      break;
58
82.7k
    case 'a':
59
83.2k
    case 'b':
60
85.9k
    case 'c':
61
87.1k
    case 'd':
62
87.3k
    case 'e':
63
91.0k
    case 'f':
64
91.0k
      r |= ((uint64_t) (hexstr[i] - 'a' + 10)) << ((l - i - 1) * 4);
65
91.0k
      break;
66
17.1k
    case 'A':
67
17.2k
    case 'B':
68
18.1k
    case 'C':
69
18.3k
    case 'D':
70
21.5k
    case 'E':
71
21.8k
    case 'F':
72
21.8k
      r |= ((uint64_t) (hexstr[i] - 'A' + 10)) << ((l - i - 1) * 4);
73
21.8k
      break;
74
0
    default:
75
0
      i = l;  // force loop exit
76
130k
    }
77
130k
  }
78
79
65.3k
  return r;
80
65.3k
}
81
82
/*
83
84
strlcpy and strlcat are defined in FreeBSD and OpenBSD,
85
the following implementations were taken from OpenBSD.
86
87
*/
88
89
#if !HAVE_STRLCPY && !defined(strlcpy)
90
size_t strlcpy(char* dst, const char* src, size_t size)
91
68.9k
{
92
68.9k
  register char* d = dst;
93
68.9k
  register const char* s = src;
94
68.9k
  register size_t n = size;
95
96
  // Copy as many bytes as will fit
97
98
68.9k
  if (n != 0 && --n != 0)
99
68.9k
  {
100
68.9k
    do
101
1.72M
    {
102
1.72M
      if ((*d++ = *s++) == 0)
103
35.7k
        break;
104
105
1.72M
    } while (--n != 0);
106
68.9k
  }
107
108
  // Not enough room in dst, add NUL and traverse rest of src
109
110
68.9k
  if (n == 0)
111
33.2k
  {
112
33.2k
    if (size != 0)
113
33.2k
      *d = '\0';  // NULL-terminate dst
114
115
97.1k
    while (*s++)
116
63.9k
      ;
117
33.2k
  }
118
119
68.9k
  return (s - src - 1);  // count does not include NULL
120
68.9k
}
121
#endif
122
123
#if !HAVE_STRLCAT && !defined(strlcat)
124
size_t strlcat(char* dst, const char* src, size_t size)
125
11.9k
{
126
11.9k
  register char* d = dst;
127
11.9k
  register const char* s = src;
128
11.9k
  register size_t n = size;
129
11.9k
  size_t dlen;
130
131
  // Find the end of dst and adjust bytes left but don't go past end
132
133
529k
  while (n-- != 0 && *d != '\0') d++;
134
135
11.9k
  dlen = d - dst;
136
11.9k
  n = size - dlen;
137
138
11.9k
  if (n == 0)
139
0
    return (dlen + strlen(s));
140
141
23.9k
  while (*s != '\0')
142
11.9k
  {
143
11.9k
    if (n != 1)
144
10.3k
    {
145
10.3k
      *d++ = *s;
146
10.3k
      n--;
147
10.3k
    }
148
11.9k
    s++;
149
11.9k
  }
150
151
11.9k
  *d = '\0';
152
153
11.9k
  return (dlen + (s - src));  // count does not include NULL
154
11.9k
}
155
#endif
156
157
int strnlen_w(const char* w_str)
158
8.36k
{
159
8.36k
  int len = 0;
160
161
2.13M
  while (w_str[0] || w_str[1])
162
2.12M
  {
163
2.12M
    w_str += 2;
164
2.12M
    len += 1;
165
2.12M
  }
166
167
8.36k
  return len;
168
8.36k
}
169
170
int strcmp_w(const char* w_str, const char* str)
171
15.0k
{
172
112k
  while (*str != 0 && w_str[0] == *str && w_str[1] == 0)
173
97.0k
  {
174
97.0k
    w_str += 2;
175
97.0k
    str += 1;
176
97.0k
  }
177
178
  // Higher-order byte of wide char non-zero? -> w_str is larger than str
179
180
15.0k
  if (w_str[1] != 0)
181
4.02k
    return 1;
182
183
11.0k
  return w_str[0] - *str;
184
15.0k
}
185
186
size_t strlcpy_w(char* dst, const char* w_src, size_t n)
187
7.54k
{
188
7.54k
  register char* d = dst;
189
7.54k
  register const char* s = w_src;
190
191
123k
  while (n > 1 && *s != 0)
192
115k
  {
193
115k
    *d = *s;
194
115k
    d += 1;
195
115k
    n -= 1;
196
115k
    s += 2;
197
115k
  }
198
199
303k
  while (*s) s += 2;
200
201
7.54k
  *d = '\0';
202
203
7.54k
  return (s - w_src) / 2;
204
7.54k
}
205
206
#if !HAVE_MEMMEM && !defined(memmem)
207
void* memmem(
208
    const void* haystack,
209
    size_t haystack_size,
210
    const void* needle,
211
    size_t needle_size)
212
{
213
  char* sp = (char*) haystack;
214
  char* pp = (char*) needle;
215
  char* eos;
216
217
  if (haystack == NULL || haystack_size == 0 || needle == NULL ||
218
      needle_size == 0)
219
    return NULL;
220
221
  eos = sp + haystack_size - needle_size;
222
223
  while (sp <= eos)
224
  {
225
    if (*sp == *pp && memcmp(sp, pp, needle_size) == 0)
226
      return sp;
227
228
    sp++;
229
  }
230
231
  return NULL;
232
}
233
#endif
234
235
///////////////////////////////////////////////////////////////////////////////
236
// This our own implementation of isalnum(). The library version is locale
237
// dependent in some platforms and can consider non-ASCII characters to be
238
// alphanumeric.
239
//
240
int yr_isalnum(const uint8_t* s)
241
0
{
242
0
  return (*s >= 0x30 && *s <= 0x39) || (*s >= 0x41 && *s <= 0x5a) ||
243
0
         (*s >= 0x61 && *s <= 0x7a);
244
0
}
245
246
//////////////////////////////////////////////////////////////////////////
247
// This our own implementation of vasprintf(), as it is not available on
248
// some platforms. It is based on the implementation of vsnprintf but it
249
// allocates memory using yr_malloc, and therefore the caller must free
250
// the memory using yr_free.
251
//
252
void yr_vasprintf(char** strp, const char* fmt, va_list ap)
253
0
{
254
0
  va_list ap_copy;
255
0
  va_copy(ap_copy, ap);
256
0
  *strp = NULL;
257
258
0
  int len = vsnprintf(NULL, 0, fmt, ap_copy);
259
260
0
  va_end(ap_copy);
261
262
0
  if (len < 0)
263
0
    return;
264
265
0
  *strp = (char*) yr_malloc(len + 1);
266
267
0
  if (*strp == NULL)
268
0
    return;
269
270
0
  vsnprintf(*strp, len + 1, fmt, ap);
271
0
}
272
273
//////////////////////////////////////////////////////////////////////////
274
// This our own implementation of asprintf(), see yr_vasprintf() for details.
275
//
276
void yr_asprintf(char** strp, const char* fmt, ...)
277
0
{
278
0
  va_list ap;
279
0
  va_start(ap, fmt);
280
0
  yr_vasprintf(strp, fmt, ap);
281
  va_end(ap);
282
0
}