1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2 
3 #include <r_util.h>
4 #if __UNIX__
5 #include <sys/mman.h>
6 #endif
7 
8 #define SET_BIT(p,n) ((p) |= (1 << (n)))
9 #define CLR_BIT(p,n) ((p) &= (~(1) << (n)))
10 
11 // TODO: find better name (r_mem_length()); is this used somewhere?
r_mem_count(const ut8 ** addr)12 R_API int r_mem_count(const ut8 **addr) {
13 	int i = 0;
14 	while (*addr++) {
15 		i++;
16 	}
17 	return i;
18 }
19 
r_mem_eq(ut8 * a,ut8 * b,int len)20 R_API int r_mem_eq(ut8 *a, ut8 *b, int len) {
21 	register int i;
22 	for (i = 0; i < len; i++) {
23 		if (a[i] != b[i]) {
24 			return false;
25 		}
26 	}
27 	return true;
28 }
29 
r_mem_copyloop(ut8 * dest,const ut8 * orig,int dsize,int osize)30 R_API void r_mem_copyloop(ut8 *dest, const ut8 *orig, int dsize, int osize) {
31 	int i = 0, j;
32 	while (i < dsize) {
33 		for (j = 0; j < osize && i < dsize; j++) {
34 			dest[i++] = orig[j];
35 		}
36 	}
37 }
38 
r_mem_cmp_mask(const ut8 * dest,const ut8 * orig,const ut8 * mask,int len)39 R_API int r_mem_cmp_mask(const ut8 *dest, const ut8 *orig, const ut8 *mask, int len) {
40 	ut8 *mdest = malloc (len);
41 	if (!mdest) {
42 		return -1;
43 	}
44 	ut8 *morig = malloc (len);
45 	if (!morig) {
46 		free (mdest);
47 		return -1;
48 	}
49 	int i;
50 	for (i = 0; i < len; i++) {
51 		mdest[i] = dest[i] & mask[i];
52 		morig[i] = orig[i] & mask[i];
53 	}
54 	int ret = memcmp (mdest, morig, len);
55 	free (mdest);
56 	free (morig);
57 	return ret;
58 }
59 
r_mem_copybits(ut8 * dst,const ut8 * src,int bits)60 R_API void r_mem_copybits(ut8 *dst, const ut8 *src, int bits) {
61 	ut8 srcmask, dstmask;
62 	int bytes = (int) (bits / 8);
63 	bits = bits % 8;
64 	memcpy (dst, src, bytes);
65 	if (bits) {
66 		srcmask = dstmask = 0;
67 		switch (bits) {
68 		case 1: srcmask = 0x80; dstmask = 0x7f; break;
69 		case 2: srcmask = 0xc0; dstmask = 0x3f; break;
70 		case 3: srcmask = 0xe0; dstmask = 0x1f; break;
71 		case 4: srcmask = 0xf0; dstmask = 0x0f; break;
72 		case 5: srcmask = 0xf8; dstmask = 0x07; break;
73 		case 6: srcmask = 0xfc; dstmask = 0x03; break;
74 		case 7: srcmask = 0xfe; dstmask = 0x01; break;
75 		}
76 		dst[bytes] = ((dst[bytes] & dstmask) | (src[bytes] & srcmask));
77 	}
78 }
79 
readbit(const ut8 * src,int bitoffset)80 static inline char readbit(const ut8 *src, int bitoffset) {
81 	const int wholeBytes = bitoffset / 8;
82 	const int remainingBits = bitoffset % 8;
83 	// return (src[wholeBytes] >> remainingBits) & 1;
84 	return (src[wholeBytes] & 1<< remainingBits);
85 }
86 
writebit(ut8 * dst,int i,bool c)87 static inline void writebit (ut8 *dst, int i, bool c) {
88 	const int byte = i / 8;
89 	const int bit = (i % 8);
90 	// eprintf ("Write %d %d = %d\n", byte, bit, c);
91 	dst += byte;
92 	if (c) {
93 		//dst[byte] |= (1 << bit);
94 		R_BIT_SET (dst , bit);
95 	} else {
96 		//dst[byte] &= (1 << bit);
97 		R_BIT_UNSET (dst , bit);
98 	}
99 }
100 
r_mem_copybits_delta(ut8 * dst,int doff,const ut8 * src,int soff,int bits)101 R_API void r_mem_copybits_delta(ut8 *dst, int doff, const ut8 *src, int soff, int bits) {
102 	int i;
103 	if (doff < 0 || soff < 0 || !dst || !src) {
104 		return;
105 	}
106 	for (i = 0; i < bits; i++) {
107 		bool c = readbit (src, i + soff);
108 		writebit (dst, i + doff, c);
109 	}
110 }
111 
r_mem_get_num(const ut8 * b,int size)112 R_API ut64 r_mem_get_num(const ut8 *b, int size) {
113 	// LITTLE ENDIAN is the default for streams
114 	switch (size) {
115 	case 1:
116 		return r_read_le8 (b);
117 	case 2:
118 		return r_read_le16 (b);
119 	case 4:
120 		return r_read_le32 (b);
121 	case 8:
122 		return r_read_le64 (b);
123 	}
124 	return 0LL;
125 }
126 
127 // TODO: SEE: R_API ut64 r_reg_get_value(RReg *reg, RRegItem *item) { .. dupped code?
r_mem_set_num(ut8 * dest,int dest_size,ut64 num)128 R_API int r_mem_set_num(ut8 *dest, int dest_size, ut64 num) {
129 	// LITTLE ENDIAN is the default for streams
130 	switch (dest_size) {
131 	case 1:
132 		r_write_le8 (dest, (ut8) (num & UT8_MAX));
133 		break;
134 	case 2:
135 		r_write_le16 (dest, (ut16) (num & UT16_MAX));
136 		break;
137 	case 4:
138 		r_write_le32 (dest, (ut32) (num & UT32_MAX));
139 		break;
140 	case 8:
141 		r_write_le64 (dest, num);
142 		break;
143 	default:
144 		return false;
145 	}
146 	return true;
147 }
148 
149 // The default endian is LE for streams.
150 // This function either swaps or copies len bytes depending on bool big_endian
151 // TODO: Remove completely
r_mem_swaporcopy(ut8 * dest,const ut8 * src,int len,bool big_endian)152 R_API void r_mem_swaporcopy(ut8 *dest, const ut8 *src, int len, bool big_endian) {
153 	if (big_endian) {
154 		r_mem_swapendian (dest, src, len);
155 	} else {
156 		memcpy (dest, src, len);
157 	}
158 }
159 
160 // This function unconditionally swaps endian of size bytes of orig -> dest
161 // TODO: Remove completely
r_mem_swapendian(ut8 * dest,const ut8 * orig,int size)162 R_API void r_mem_swapendian(ut8 *dest, const ut8 *orig, int size) {
163 	ut8 buffer[8];
164 	switch (size) {
165 	case 1:
166 		*dest = *orig;
167 		break;
168 	case 2:
169 		*buffer = *orig;
170 		dest[0] = orig[1];
171 		dest[1] = buffer[0];
172 		break;
173 	case 3:
174 		*buffer = *orig;
175 		dest[0] = orig[2];
176 		dest[1] = orig[1];
177 		dest[2] = buffer[0];
178 		break;
179 	case 4:
180 		memcpy (buffer, orig, 4);
181 		dest[0] = buffer[3];
182 		dest[1] = buffer[2];
183 		dest[2] = buffer[1];
184 		dest[3] = buffer[0];
185 		break;
186 	case 8:
187 		memcpy (buffer, orig, 8);
188 		dest[0] = buffer[7];
189 		dest[1] = buffer[6];
190 		dest[2] = buffer[5];
191 		dest[3] = buffer[4];
192 		dest[4] = buffer[3];
193 		dest[5] = buffer[2];
194 		dest[6] = buffer[1];
195 		dest[7] = buffer[0];
196 		break;
197 	default:
198 		if (dest != orig) {
199 			memmove (dest, orig, size);
200 		}
201 	}
202 }
203 
204 // R_DOC r_mem_mem: Finds the needle of nlen size into the haystack of hlen size
205 // R_UNIT printf("%s\n", r_mem_mem("food is pure lame", 20, "is", 2));
r_mem_mem(const ut8 * haystack,int hlen,const ut8 * needle,int nlen)206 R_API const ut8 *r_mem_mem(const ut8 *haystack, int hlen, const ut8 *needle, int nlen) {
207 	int i, until = hlen - nlen + 1;
208 	if (hlen < 1 || nlen < 1) {
209 		return NULL;
210 	}
211 	for (i = 0; i < until; i++) {
212 		if (!memcmp (haystack + i, needle, nlen)) {
213 			return haystack + i;
214 		}
215 	}
216 	return NULL;
217 }
218 
219 // TODO: rename to r_mem_mem and refactor all calls to this function
r_mem_mem_aligned(const ut8 * haystack,int hlen,const ut8 * needle,int nlen,int align)220 R_API const ut8 *r_mem_mem_aligned(const ut8 *haystack, int hlen, const ut8 *needle, int nlen, int align) {
221 	int i, until = hlen - nlen + 1;
222 	if (align < 1) {
223 		align = 1;
224 	}
225 	if (hlen < 1 || nlen < 1) {
226 		return NULL;
227 	}
228 	if (align > 1) {
229 		until -= (until % align);
230 	}
231 	for (i = 0; i < until; i += align) {
232 		if (!memcmp (haystack + i, needle, nlen)) {
233 			return haystack + i;
234 		}
235 	}
236 	return NULL;
237 }
238 
r_mem_protect(void * ptr,int size,const char * prot)239 R_API int r_mem_protect(void *ptr, int size, const char *prot) {
240 #if __UNIX__
241 	int p = 0;
242 	if (strchr (prot, 'x')) {
243 		p |= PROT_EXEC;
244 	}
245 	if (strchr (prot, 'r')) {
246 		p |= PROT_READ;
247 	}
248 	if (strchr (prot, 'w')) {
249 		p |= PROT_WRITE;
250 	}
251 	if (mprotect (ptr, size, p) == -1) {
252 		return false;
253 	}
254 #elif __WINDOWS__
255 	int r, w, x;
256 	DWORD p = PAGE_NOACCESS;
257 	r = strchr (prot, 'r')? 1: 0;
258 	w = strchr (prot, 'w')? 1: 0;
259 	x = strchr (prot, 'x')? 1: 0;
260 	if (w && x) {
261 		return false;
262 	}
263 	if (x) {
264 		p = PAGE_EXECUTE_READ;
265 	} else if (w) {
266 		p = PAGE_READWRITE;
267 	} else if (r) {
268 		p = PAGE_READONLY;
269 	}
270 	if (!VirtualProtect (ptr, size, p, NULL)) {
271 		return false;
272 	}
273 #else
274 #warning Unknown platform
275 #endif
276 	return true;
277 }
278 
r_mem_dup(const void * s,int l)279 R_API void *r_mem_dup(const void *s, int l) {
280 	void *d = malloc (l);
281 	if (d) {
282 		memcpy (d, s, l);
283 	}
284 	return d;
285 }
286 
r_mem_reverse(ut8 * b,int l)287 R_API void r_mem_reverse(ut8 *b, int l) {
288 	ut8 tmp;
289 	int i, end = l / 2;
290 	for (i = 0; i < end; i++) {
291 		tmp = b[i];
292 		b[i] = b[l - i - 1];
293 		b[l - i - 1] = tmp;
294 	}
295 }
296 
r_mem_is_printable(const ut8 * a,int la)297 R_API bool r_mem_is_printable(const ut8 *a, int la) {
298 	int i;
299 	for (i = 0; i < la; i++) {
300 		if (a[i] != '\n' && a[i] != '\t' && !IS_PRINTABLE (a[i])) {
301 			return false;
302 		}
303 	}
304 	return true;
305 }
306 
r_mem_is_zero(const ut8 * b,int l)307 R_API bool r_mem_is_zero(const ut8 *b, int l) {
308 	int i;
309 	for (i = 0; i < l; i++) {
310 		if (b[i]) {
311 			return false;
312 		}
313 	}
314 	return true;
315 }
316 
r_mem_alloc(int sz)317 R_API void *r_mem_alloc(int sz) {
318 	return calloc (sz, 1);
319 }
320 
r_mem_free(void * p)321 R_API void r_mem_free(void *p) {
322 	free (p);
323 }
324 
r_mem_memzero(void * dst,size_t l)325 R_API void r_mem_memzero(void *dst, size_t l) {
326 #ifdef _MSC_VER
327 	RtlSecureZeroMemory (dst, l);
328 #else
329 #if HAVE_EXPLICIT_BZERO
330 	explicit_bzero (dst, l);
331 #elif HAVE_EXPLICIT_MEMSET
332 	(void)explicit_memset (dst, 0, l);
333 #else
334 	memset (dst, 0, l);
335 	__asm__ volatile ("" :: "r"(dst) : "memory");
336 #endif
337 #endif
338 }
339 
r_mem_mmap_resize(RMmap * m,ut64 newsize)340 R_API void *r_mem_mmap_resize(RMmap *m, ut64 newsize) {
341 #if __WINDOWS__
342 	if (m->fm != INVALID_HANDLE_VALUE) {
343 		CloseHandle (m->fm);
344 	}
345 	if (m->fh != INVALID_HANDLE_VALUE) {
346 		CloseHandle (m->fh);
347 	}
348 	if (m->buf) {
349 		UnmapViewOfFile (m->buf);
350 	}
351 #elif __UNIX__
352 	if (munmap (m->buf, m->len) != 0) {
353 		return NULL;
354 	}
355 #endif
356 	if (!r_sys_truncate (m->filename, newsize)) {
357 		return NULL;
358 	}
359 	m->len = newsize;
360 	r_file_mmap_arch (m, m->filename, m->fd);
361 	return m->buf;
362 }
363