Coverage Report

Created: 2025-08-28 06:43

/src/capstonenext/utils.c
Line
Count
Source (jump to first uncovered line)
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
6.40M
{
19
6.40M
  unsigned int c;
20
21
8.47M
  for (c = 0; list[c] > 0; c++)
22
2.07M
    ;
23
24
6.40M
  return c;
25
6.40M
}
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
3.20M
{
31
3.20M
  unsigned int c;
32
33
5.54M
  for (c = 0; list[c] > 0; c++)
34
2.33M
    ;
35
36
3.20M
  return c;
37
3.20M
}
38
39
char *cs_strdup(const char *str)
40
205k
{
41
205k
  size_t len = strlen(str) + 1;
42
205k
  void *new = cs_mem_malloc(len);
43
44
205k
  if (new == NULL)
45
0
    return NULL;
46
47
205k
  return (char *)memmove(new, str, len);
48
205k
}
49
50
// we need this since Windows doesn't have snprintf()
51
int cs_snprintf(char *buffer, size_t size, const char *fmt, ...)
52
206k
{
53
206k
  int ret;
54
55
206k
  va_list ap;
56
206k
  va_start(ap, fmt);
57
206k
  ret = cs_vsnprintf(buffer, size, fmt, ap);
58
206k
  va_end(ap);
59
60
206k
  return ret;
61
206k
}
62
63
bool arr_exist8(unsigned char *arr, unsigned char max, unsigned int id)
64
0
{
65
0
  int i;
66
67
0
  for (i = 0; i < max; i++) {
68
0
    if (arr[i] == id)
69
0
      return true;
70
0
  }
71
72
0
  return false;
73
0
}
74
75
bool arr_exist(uint16_t *arr, unsigned char max, unsigned int id)
76
1.29M
{
77
1.29M
  int i;
78
79
1.36M
  for (i = 0; i < max; i++) {
80
168k
    if (arr[i] == id)
81
93.2k
      return true;
82
168k
  }
83
84
1.19M
  return false;
85
1.29M
}
86
87
/// @brief Checks if the @id is in the @table. @table has @table_size elements.
88
/// @param table The table with the values to compare to.
89
/// @param table_size The number elements in the table.
90
/// @param id The identifier to search for in the table.
91
/// @return True if @id is part of the @table, false otherwise.
92
bool arr_exist_int(int *table, size_t table_size, int id)
93
0
{
94
0
  int i;
95
0
  for (i = 0; i < table_size; i++) {
96
0
    if (table[i] == id)
97
0
      return true;
98
0
  }
99
100
0
  return false;
101
0
}
102
103
/// Reads 8 bytes in the endian order specified in MI->cs->mode.
104
uint64_t readBytes64(MCInst *MI, const uint8_t *Bytes)
105
0
{
106
0
  assert(MI && Bytes);
107
0
  uint64_t Insn;
108
0
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
109
0
    Insn = ((uint64_t)Bytes[7] << 0) | ((uint64_t)Bytes[6] << 8) |
110
0
           ((uint64_t)Bytes[5] << 16) | ((uint64_t)Bytes[4] << 24) |
111
0
           ((uint64_t)Bytes[3] << 32) | ((uint64_t)Bytes[2] << 40) |
112
0
           ((uint64_t)Bytes[1] << 48) | ((uint64_t)Bytes[0] << 56);
113
0
  else
114
0
    Insn = ((uint64_t)Bytes[7] << 56) | ((uint64_t)Bytes[6] << 48) |
115
0
           ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |
116
0
           ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |
117
0
           ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);
118
0
  return Insn;
119
0
}
120
121
/// Reads 6 bytes in the endian order specified in MI->cs->mode.
122
uint64_t readBytes48(MCInst *MI, const uint8_t *Bytes)
123
57.5k
{
124
57.5k
  assert(MI && Bytes);
125
57.5k
  uint64_t Insn;
126
57.5k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
127
57.5k
    Insn = ((uint64_t)Bytes[5] << 0) | ((uint64_t)Bytes[4] << 8) |
128
57.5k
           ((uint64_t)Bytes[3] << 16) | ((uint64_t)Bytes[2] << 24) |
129
57.5k
           ((uint64_t)Bytes[1] << 32) | ((uint64_t)Bytes[0] << 40);
130
0
  else
131
0
    Insn = ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |
132
0
           ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |
133
0
           ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);
134
57.5k
  return Insn;
135
57.5k
}
136
137
/// Reads 4 bytes in the endian order specified in MI->cs->mode.
138
uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes)
139
860k
{
140
860k
  assert(MI && Bytes);
141
860k
  uint32_t Insn;
142
860k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
143
412k
    Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |
144
412k
           ((uint32_t)Bytes[0] << 24);
145
448k
  else
146
448k
    Insn = ((uint32_t)Bytes[3] << 24) | (Bytes[2] << 16) |
147
448k
           (Bytes[1] << 8) | (Bytes[0] << 0);
148
860k
  return Insn;
149
860k
}
150
151
/// Reads 3 bytes in the endian order specified in MI->cs->mode.
152
uint32_t readBytes24(MCInst *MI, const uint8_t *Bytes)
153
75.0k
{
154
75.0k
  assert(MI && Bytes);
155
75.0k
  uint32_t Insn;
156
75.0k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
157
0
    Insn = (Bytes[2]) | (Bytes[1] << 8) |
158
0
           ((uint32_t)Bytes[0] << 16);
159
75.0k
  else
160
75.0k
    Insn = (Bytes[2] << 16) | (Bytes[1] << 8) |
161
75.0k
           ((uint32_t)Bytes[0]);
162
75.0k
  return Insn;
163
75.0k
}
164
165
/// Reads 2 bytes in the endian order specified in MI->cs->mode.
166
uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes)
167
1.33M
{
168
1.33M
  assert(MI && Bytes);
169
1.33M
  uint16_t Insn;
170
1.33M
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
171
45.2k
    Insn = (Bytes[0] << 8) | Bytes[1];
172
1.29M
  else
173
1.29M
    Insn = (Bytes[1] << 8) | Bytes[0];
174
175
1.33M
  return Insn;
176
1.33M
}
177
178
/// @brief Appends the string @p src to the string @p str. @p src is put to lower case.
179
/// @param str The string to append to.
180
/// @param str_size The length of @p str
181
/// @param src The string to append.
182
/// Does nothing if any of the given strings is NULL.
183
void append_to_str_lower(char *str, size_t str_size, const char *src)
184
4.99k
{
185
4.99k
  if (!str || !src) {
186
0
    return;
187
0
  }
188
4.99k
  char *dest = strchr(str, '\0');
189
4.99k
  if (dest - str >= str_size) {
190
0
    assert("str_size does not match actual string length." && 0);
191
0
    return;
192
0
  }
193
194
4.99k
  int i = dest - str;
195
31.6k
  for (int j = 0; (i < str_size) && (j < strlen(src)); ++i, ++j) {
196
26.6k
    str[i] = tolower(src[j]);
197
26.6k
  }
198
4.99k
  str[i] = '\0';
199
4.99k
}
200
201
/// @brief Appends the string @p src to the string @p dest.
202
/// @p dest is can be a stack allocated buffer.
203
///
204
/// @param dest The string to append to.
205
/// @param dest_buf_size Size of buffer @p str.
206
/// @param src The string to append.
207
/// Does nothing if any of the given strings is NULL.
208
void str_append_no_realloc(char *dest, size_t dest_buf_size, const char *src)
209
0
{
210
0
  if (!dest || !src) {
211
0
    return;
212
0
  }
213
0
  if (strlen(dest) + strlen(src) + 1 > dest_buf_size) {
214
0
    printf("str_size does not match actual string length.\n");
215
0
    return;
216
0
  }
217
0
  strncat(dest, src, dest_buf_size - strlen(dest));
218
0
}
219
220
/// Allocates memory of strlen(str_a) + strlen(str_b) + 1 chars
221
/// and copies all strings into it as str_a + str_b
222
/// str_a is passed to realloc and should not be used afterwards.
223
/// Returns the concatenated string.
224
/// Returns NULL in case of failure.
225
char *str_append(char *str_a, const char *str_b)
226
0
{
227
0
  if (!str_a || !str_b) {
228
0
    return NULL;
229
0
  }
230
0
  size_t asize = strlen(str_a) + strlen(str_b) + 1;
231
0
  str_a = realloc(str_a, asize);
232
0
  strncat(str_a, str_b, asize - strlen(str_a));
233
0
  return str_a;
234
0
}
235
236
/// Returns the given byte sequence @bytes as a string of the
237
/// form: 0xXX,0xXX...
238
/// Returns NULL in case of failure.
239
char *byte_seq_to_str(uint8_t *bytes, size_t len)
240
0
{
241
0
  if (!bytes) {
242
0
    return NULL;
243
0
  }
244
0
  if (len == 0) {
245
0
    return NULL;
246
0
  }
247
0
  char single_byte[8] = { 0 };
248
0
  char *s = calloc(sizeof(char), 32);
249
0
  for (size_t i = 0; i < len; ++i) {
250
0
    cs_snprintf(single_byte, sizeof(single_byte),
251
0
          "0x%02" PRIx8 "%s", bytes[i],
252
0
          i == len - 1 ? "" : ", ");
253
0
    s = str_append(s, single_byte);
254
0
    if (!s) {
255
0
      return NULL;
256
0
    }
257
0
  }
258
0
  return s;
259
0
}