Coverage Report

Created: 2026-04-12 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/utils.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
4
#if defined(CAPSTONE_HAS_OSXKERNEL)
5
#include <Availability.h>
6
#include <libkern/libkern.h>
7
#else
8
#include <stdlib.h>
9
#endif
10
#include <string.h>
11
#include <ctype.h>
12
13
#include "utils.h"
14
15
// count number of positive members in a list.
16
// NOTE: list must be guaranteed to end in 0
17
unsigned int count_positive(const uint16_t *list)
18
1.12M
{
19
1.12M
  unsigned int c;
20
21
1.86M
  for (c = 0; list[c] > 0; c++)
22
744k
    ;
23
24
1.12M
  return c;
25
1.12M
}
26
27
// count number of positive members in a list.
28
// NOTE: list must be guaranteed to end in 0
29
unsigned int count_positive8(const unsigned char *list)
30
560k
{
31
560k
  unsigned int c;
32
33
815k
  for (c = 0; list[c] > 0; c++)
34
254k
    ;
35
36
560k
  return c;
37
560k
}
38
39
char *cs_strdup(const char *str)
40
0
{
41
0
  size_t len = strlen(str) + 1;
42
0
  void *new = cs_mem_malloc(len);
43
44
0
  if (new == NULL)
45
0
    return NULL;
46
47
0
  return (char *)memmove(new, str, len);
48
0
}
49
50
// Portable strnlen replacement for platforms that lack it
51
// (e.g. Mac OS X 10.5 Leopard).
52
size_t cs_strnlen(const char *str, size_t n)
53
0
{
54
0
  if (!str)
55
0
    return 0;
56
57
0
  size_t l = 0;
58
59
0
  while (l < n && str[l] != '\0')
60
0
    l++;
61
62
0
  return l;
63
0
}
64
65
// we need this since Windows doesn't have snprintf()
66
int cs_snprintf(char *buffer, size_t size, const char *fmt, ...)
67
37.9k
{
68
37.9k
  int ret;
69
70
37.9k
  va_list ap;
71
37.9k
  va_start(ap, fmt);
72
37.9k
  ret = cs_vsnprintf(buffer, size, fmt, ap);
73
37.9k
  va_end(ap);
74
75
37.9k
  return ret;
76
37.9k
}
77
78
bool arr_exist8(unsigned char *arr, unsigned char max, unsigned int id)
79
0
{
80
0
  int i;
81
82
0
  for (i = 0; i < max; i++) {
83
0
    if (arr[i] == id)
84
0
      return true;
85
0
  }
86
87
0
  return false;
88
0
}
89
90
bool arr_exist(uint16_t *arr, unsigned char max, unsigned int id)
91
0
{
92
0
  int i;
93
94
0
  for (i = 0; i < max; i++) {
95
0
    if (arr[i] == id)
96
0
      return true;
97
0
  }
98
99
0
  return false;
100
0
}
101
102
/// @brief Checks if the @id is in the @table. @table has @table_size elements.
103
/// @param table The table with the values to compare to.
104
/// @param table_size The number elements in the table.
105
/// @param id The identifier to search for in the table.
106
/// @return True if @id is part of the @table, false otherwise.
107
bool arr_exist_int(int *table, size_t table_size, int id)
108
0
{
109
0
  int i;
110
0
  for (i = 0; i < table_size; i++) {
111
0
    if (table[i] == id)
112
0
      return true;
113
0
  }
114
115
0
  return false;
116
0
}
117
118
/// Reads 8 bytes in the endian order specified in MI->cs->mode.
119
uint64_t readBytes64(MCInst *MI, const uint8_t *Bytes)
120
0
{
121
0
  assert(MI && Bytes);
122
0
  uint64_t Insn;
123
0
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
124
0
    Insn = ((uint64_t)Bytes[7] << 0) | ((uint64_t)Bytes[6] << 8) |
125
0
           ((uint64_t)Bytes[5] << 16) | ((uint64_t)Bytes[4] << 24) |
126
0
           ((uint64_t)Bytes[3] << 32) | ((uint64_t)Bytes[2] << 40) |
127
0
           ((uint64_t)Bytes[1] << 48) | ((uint64_t)Bytes[0] << 56);
128
0
  else
129
0
    Insn = ((uint64_t)Bytes[7] << 56) | ((uint64_t)Bytes[6] << 48) |
130
0
           ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |
131
0
           ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |
132
0
           ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);
133
0
  return Insn;
134
0
}
135
136
/// Reads 6 bytes in the endian order specified in MI->cs->mode.
137
uint64_t readBytes48(MCInst *MI, const uint8_t *Bytes)
138
35.5k
{
139
35.5k
  assert(MI && Bytes);
140
35.5k
  uint64_t Insn;
141
35.5k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
142
35.5k
    Insn = ((uint64_t)Bytes[5] << 0) | ((uint64_t)Bytes[4] << 8) |
143
35.5k
           ((uint64_t)Bytes[3] << 16) | ((uint64_t)Bytes[2] << 24) |
144
35.5k
           ((uint64_t)Bytes[1] << 32) | ((uint64_t)Bytes[0] << 40);
145
0
  else
146
0
    Insn = ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |
147
0
           ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |
148
0
           ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);
149
35.5k
  return Insn;
150
35.5k
}
151
152
/// Reads 4 bytes in the endian order specified in MI->cs->mode.
153
uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes)
154
503k
{
155
503k
  assert(MI && Bytes);
156
503k
  uint32_t Insn;
157
503k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
158
215k
    Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |
159
215k
           ((uint32_t)Bytes[0] << 24);
160
287k
  else
161
287k
    Insn = ((uint32_t)Bytes[3] << 24) | (Bytes[2] << 16) |
162
287k
           (Bytes[1] << 8) | (Bytes[0] << 0);
163
503k
  return Insn;
164
503k
}
165
166
/// Reads 3 bytes in the endian order specified in MI->cs->mode.
167
uint32_t readBytes24(MCInst *MI, const uint8_t *Bytes)
168
48.8k
{
169
48.8k
  assert(MI && Bytes);
170
48.8k
  uint32_t Insn;
171
48.8k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
172
0
    Insn = (Bytes[2]) | (Bytes[1] << 8) |
173
0
           ((uint32_t)Bytes[0] << 16);
174
48.8k
  else
175
48.8k
    Insn = (Bytes[2] << 16) | (Bytes[1] << 8) |
176
48.8k
           ((uint32_t)Bytes[0]);
177
48.8k
  return Insn;
178
48.8k
}
179
180
/// Reads 2 bytes in the endian order specified in MI->cs->mode.
181
uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes)
182
852k
{
183
852k
  assert(MI && Bytes);
184
852k
  uint16_t Insn;
185
852k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
186
30.1k
    Insn = (Bytes[0] << 8) | Bytes[1];
187
821k
  else
188
821k
    Insn = (Bytes[1] << 8) | Bytes[0];
189
190
852k
  return Insn;
191
852k
}
192
193
/// @brief Appends the string @p src to the string @p str. @p src is put to lower case.
194
/// @param str The string to append to.
195
/// @param str_size The length of @p str
196
/// @param src The string to append.
197
/// Does nothing if any of the given strings is NULL.
198
void append_to_str_lower(char *str, size_t str_size, const char *src)
199
4.67k
{
200
4.67k
  if (!str || !src) {
201
0
    return;
202
0
  }
203
4.67k
  char *dest = strchr(str, '\0');
204
4.67k
  if (dest - str >= str_size) {
205
0
    assert("str_size does not match actual string length." && 0);
206
0
    return;
207
0
  }
208
209
4.67k
  int i = dest - str;
210
31.5k
  for (int j = 0; (i < str_size) && (j < strlen(src)); ++i, ++j) {
211
26.8k
    str[i] = tolower(src[j]);
212
26.8k
  }
213
4.67k
  str[i] = '\0';
214
4.67k
}
215
216
/// @brief Appends the string @p src to the string @p dest.
217
/// @p dest is can be a stack allocated buffer.
218
///
219
/// @param dest The string to append to.
220
/// @param dest_buf_size Size of buffer @p str.
221
/// @param src The string to append.
222
/// Does nothing if any of the given strings is NULL.
223
void str_append_no_realloc(char *dest, size_t dest_buf_size, const char *src)
224
0
{
225
0
  if (!dest || !src) {
226
0
    return;
227
0
  }
228
0
  if (strlen(dest) + strlen(src) + 1 > dest_buf_size) {
229
0
    printf("str_size does not match actual string length.\n");
230
0
    return;
231
0
  }
232
0
  strncat(dest, src, dest_buf_size - strlen(dest));
233
0
}
234
235
/// Allocates memory of strlen(str_a) + strlen(str_b) + 1 chars
236
/// and copies all strings into it as str_a + str_b
237
/// str_a is passed to realloc and should not be used afterwards.
238
/// Returns the concatenated string.
239
/// Returns NULL in case of failure.
240
char *str_append(char *str_a, const char *str_b)
241
0
{
242
0
  if (!str_a || !str_b) {
243
0
    return NULL;
244
0
  }
245
0
  size_t asize = strlen(str_a) + strlen(str_b) + 1;
246
0
  str_a = realloc(str_a, asize);
247
0
  strncat(str_a, str_b, asize - strlen(str_a));
248
0
  return str_a;
249
0
}
250
251
/// Returns the given byte sequence @bytes as a string of the
252
/// form: 0xXX,0xXX...
253
/// Returns NULL in case of failure.
254
char *byte_seq_to_str(uint8_t *bytes, size_t len)
255
0
{
256
0
  if (!bytes) {
257
0
    return NULL;
258
0
  }
259
0
  if (len == 0) {
260
0
    return NULL;
261
0
  }
262
0
  char single_byte[8] = { 0 };
263
0
  char *s = calloc(sizeof(char), 32);
264
0
  for (size_t i = 0; i < len; ++i) {
265
0
    cs_snprintf(single_byte, sizeof(single_byte),
266
0
          "0x%02" PRIx8 "%s", bytes[i],
267
0
          i == len - 1 ? "" : ", ");
268
0
    s = str_append(s, single_byte);
269
0
    if (!s) {
270
0
      return NULL;
271
0
    }
272
0
  }
273
0
  return s;
274
0
}