Coverage Report

Created: 2024-09-08 06:22

/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
9.58M
{
19
9.58M
  unsigned int c;
20
21
13.2M
  for (c = 0; list[c] > 0; c++);
22
23
9.58M
  return c;
24
9.58M
}
25
26
// count number of positive members in a list.
27
// NOTE: list must be guaranteed to end in 0
28
unsigned int count_positive8(const unsigned char *list)
29
4.79M
{
30
4.79M
  unsigned int c;
31
32
8.60M
  for (c = 0; list[c] > 0; c++);
33
34
4.79M
  return c;
35
4.79M
}
36
37
char *cs_strdup(const char *str)
38
134k
{
39
134k
  size_t len = strlen(str) + 1;
40
134k
  void *new = cs_mem_malloc(len);
41
42
134k
  if (new == NULL)
43
0
    return NULL;
44
45
134k
  return (char *)memmove(new, str, len);
46
134k
}
47
48
// we need this since Windows doesn't have snprintf()
49
int cs_snprintf(char *buffer, size_t size, const char *fmt, ...)
50
104k
{
51
104k
  int ret;
52
53
104k
  va_list ap;
54
104k
  va_start(ap, fmt);
55
104k
  ret = cs_vsnprintf(buffer, size, fmt, ap);
56
104k
  va_end(ap);
57
58
104k
  return ret;
59
104k
}
60
61
bool arr_exist8(unsigned char *arr, unsigned char max, unsigned int id)
62
0
{
63
0
  int i;
64
65
0
  for (i = 0; i < max; i++) {
66
0
    if (arr[i] == id)
67
0
      return true;
68
0
  }
69
70
0
  return false;
71
0
}
72
73
bool arr_exist(uint16_t *arr, unsigned char max, unsigned int id)
74
1.66M
{
75
1.66M
  int i;
76
77
1.80M
  for (i = 0; i < max; i++) {
78
358k
    if (arr[i] == id)
79
220k
      return true;
80
358k
  }
81
82
1.44M
  return false;
83
1.66M
}
84
85
/// Reads 4 bytes in the endian order specified in MI->cs->mode.
86
uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes)
87
555k
{
88
555k
  assert(MI && Bytes);
89
555k
  uint32_t Insn;
90
555k
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
91
214k
    Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |
92
214k
           ((uint32_t)Bytes[0] << 24);
93
341k
  else
94
341k
    Insn = ((uint32_t)Bytes[3] << 24) | (Bytes[2] << 16) |
95
341k
           (Bytes[1] << 8) | (Bytes[0] << 0);
96
555k
  return Insn;
97
555k
}
98
99
/// Reads 2 bytes in the endian order specified in MI->cs->mode.
100
uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes)
101
0
{
102
0
  assert(MI && Bytes);
103
0
  uint16_t Insn;
104
0
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
105
0
    Insn = (Bytes[0] << 8) | Bytes[1];
106
0
  else
107
0
    Insn = (Bytes[1] << 8) | Bytes[0];
108
109
0
  return Insn;
110
0
}
111
112
/// @brief Appends the string @p src to the string @p str. @p src is put to lower case.
113
/// @param str The string to append to.
114
/// @param str_size The length of @p str
115
/// @param src The string to append.
116
/// Does nothing if any of the given strings is NULL.
117
2.76k
void append_to_str_lower(char *str, size_t str_size, const char *src) {
118
2.76k
  if (!str || !src) {
119
0
    return;
120
0
  }
121
2.76k
  char *dest = strchr(str, '\0');
122
2.76k
  if (dest - str >= str_size) {
123
0
    assert("str_size does not match actual string length." && 0);
124
0
    return;
125
0
  }
126
127
2.76k
  int i = dest - str;
128
21.3k
  for (int j = 0; (i < str_size) && (j < strlen(src)); ++i, ++j) {
129
18.5k
    str[i] = tolower(src[j]);
130
18.5k
  }
131
2.76k
  str[i] = '\0';
132
2.76k
}
133
134
/// @brief Appends the string @p src to the string @p str. @p src is put to lower case.
135
/// @param str The string to append to.
136
/// @param str_buf_size Size of buffer @p str.
137
/// @param src The string to append.
138
/// Does nothing if any of the given strings is NULL.
139
0
void append_to_str(char *str, size_t str_buf_size, const char *src) {
140
0
  if (!str || !src) {
141
0
    return;
142
0
  }
143
0
  if (strlen(str) + strlen(src) + 1 > str_buf_size) {
144
0
    assert("str_size does not match actual string length." && 0);
145
0
    return;
146
0
  }
147
0
  strncat(str, src, str_buf_size);
148
0
}
149
150
151
/// Allocates memory of strlen(str_a) + strlen(str_b) + 1 chars
152
/// and copies all strings into it as str_a + str_b
153
/// str_a is passed to realloc and should not be used afterwards.
154
/// Returns the result.
155
/// Returns NULL in case of failure.
156
0
char *str_append(char *str_a, const char *str_b) {
157
0
  if (!str_a || !str_b) {
158
0
    return NULL;
159
0
  }
160
0
  assert(str_a && str_b);
161
0
  size_t asize = strlen(str_a) + strlen(str_b) + 1;
162
0
  str_a = realloc(str_a, asize);
163
0
  strncat(str_a, str_b, asize);
164
0
  return str_a;
165
0
}
166
167
/// Returns the given byte sequence @bytes as a string of the
168
/// form: 0xXX,0xXX...
169
/// Returns NULL in case of failure.
170
char *byte_seq_to_str(uint8_t *bytes, size_t len)
171
0
{
172
0
  if (!bytes) {
173
0
    return NULL;
174
0
  }
175
0
  if (len == 0) {
176
0
    return NULL;
177
0
  }
178
0
  char single_byte[8] = { 0 };
179
0
  char *s = calloc(sizeof(char), 32);
180
0
  for (size_t i = 0; i < len; ++i) {
181
0
    cs_snprintf(single_byte, sizeof(single_byte), "0x%02" PRIx8 "%s",
182
0
          bytes[i], i == len - 1 ? "" : ",");
183
0
    s = str_append(s, single_byte);
184
0
    if (!s) {
185
0
      return NULL;
186
0
    }
187
0
  }
188
0
  return s;
189
0
}