1 /* radare - LGPL - Copyright 2009-2020 - ret2libc, pancake */
2 
3 #include <r_types.h>
4 #include <r_util.h>
5 #include <r_io.h>
6 
7 typedef enum {
8 	R_BUFFER_FILE,
9 	R_BUFFER_IO,
10 	R_BUFFER_BYTES,
11 	R_BUFFER_MMAP,
12 	R_BUFFER_SPARSE,
13 	R_BUFFER_REF,
14 } RBufferType;
15 
16 #include "buf_file.c"
17 #include "buf_sparse.c"
18 #include "buf_bytes.c"
19 #include "buf_mmap.c"
20 #include "buf_io.c"
21 #include "buf_ref.c"
22 
buf_init(RBuffer * b,const void * user)23 static bool buf_init(RBuffer *b, const void *user) {
24 	r_return_val_if_fail (b && b->methods, false);
25 	return b->methods->init? b->methods->init (b, user): true;
26 }
27 
buf_fini(RBuffer * b)28 static bool buf_fini(RBuffer *b) {
29 	r_return_val_if_fail (b && b->methods, false);
30 	return b->methods->fini? b->methods->fini (b): true;
31 }
32 
buf_get_size(RBuffer * b)33 static ut64 buf_get_size(RBuffer *b) {
34 	r_return_val_if_fail (b && b->methods, UT64_MAX);
35 	return b->methods->get_size? b->methods->get_size (b): UT64_MAX;
36 }
37 
buf_read(RBuffer * b,ut8 * buf,size_t len)38 static st64 buf_read(RBuffer *b, ut8 *buf, size_t len) {
39 	r_return_val_if_fail (b && b->methods, -1);
40 	return b->methods->read? b->methods->read (b, buf, len): -1;
41 }
42 
buf_write(RBuffer * b,const ut8 * buf,size_t len)43 static st64 buf_write(RBuffer *b, const ut8 *buf, size_t len) {
44 	r_return_val_if_fail (b && b->methods, -1);
45 	R_FREE (b->whole_buf);
46 	return b->methods->write? b->methods->write (b, buf, len): -1;
47 }
48 
buf_seek(RBuffer * b,st64 addr,int whence)49 static st64 buf_seek(RBuffer *b, st64 addr, int whence) {
50 	r_return_val_if_fail (b && b->methods, -1);
51 	return b->methods->seek? b->methods->seek (b, addr, whence): -1;
52 }
53 
buf_resize(RBuffer * b,ut64 newsize)54 static bool buf_resize(RBuffer *b, ut64 newsize) {
55 	r_return_val_if_fail (b && b->methods, -1);
56 	return b->methods->resize? b->methods->resize (b, newsize): false;
57 }
58 
get_whole_buf(RBuffer * b,ut64 * sz)59 static ut8 *get_whole_buf(RBuffer *b, ut64 *sz) {
60 	r_return_val_if_fail (b && b->methods, NULL);
61 	if (b->methods->get_whole_buf) {
62 		return b->methods->get_whole_buf (b, sz);
63 	}
64 	ut64 bsz = r_buf_size (b);
65 	// bsz = 4096; // FAKE MINIMUM SIZE TO READ THE BIN HEADER
66 	if (bsz == UT64_MAX) {
67 		return NULL;
68 	}
69 	free (b->whole_buf);
70 	b->whole_buf = R_NEWS (ut8, bsz);
71 	if (!b->whole_buf) {
72 		return NULL;
73 	}
74 	r_buf_read_at (b, 0, b->whole_buf, bsz);
75 	if (sz) {
76 		*sz = bsz;
77 	}
78 	return b->whole_buf;
79 }
80 
new_buffer(RBufferType type,const void * user)81 static RBuffer *new_buffer(RBufferType type, const void *user) {
82 	RBuffer *b = R_NEW0 (RBuffer);
83 	if (!b) {
84 		return NULL;
85 	}
86 	switch (type) {
87 	case R_BUFFER_BYTES:
88 		b->methods = &buffer_bytes_methods;
89 		break;
90 	case R_BUFFER_MMAP:
91 		b->methods = &buffer_mmap_methods;
92 		break;
93 	case R_BUFFER_SPARSE:
94 		b->methods = &buffer_sparse_methods;
95 		break;
96 	case R_BUFFER_FILE:
97 		b->methods = &buffer_file_methods;
98 		break;
99 	case R_BUFFER_IO:
100 		b->methods = &buffer_io_methods;
101 		break;
102 	case R_BUFFER_REF:
103 		b->methods = &buffer_ref_methods;
104 		break;
105 	default:
106 		r_warn_if_reached ();
107 		break;
108 	}
109 	if (!buf_init (b, user)) {
110 		free (b);
111 		return NULL;
112 	}
113 	return b;
114 }
115 
116 // TODO: Optimize to use memcpy when buffers are not in range..
117 // check buf boundaries and offsets and use memcpy or memmove
118 
119 // copied from libr/io/cache.c:r_io_cache_read
120 // ret # of bytes copied
r_buf_new_with_io(void * iob,int fd)121 R_API RBuffer *r_buf_new_with_io(void *iob, int fd) {
122 	r_return_val_if_fail (iob && fd >= 0, NULL);
123 	struct buf_io_user u = { 0 };
124 	u.iob = (RIOBind *)iob;
125 	u.fd = fd;
126 	return new_buffer (R_BUFFER_IO, &u);
127 }
128 
r_buf_new_with_pointers(const ut8 * bytes,ut64 len,bool steal)129 R_API RBuffer *r_buf_new_with_pointers(const ut8 *bytes, ut64 len, bool steal) {
130 	struct buf_bytes_user u = { 0 };
131 	u.data_steal = bytes;
132 	u.length = len;
133 	u.steal = steal;
134 	return new_buffer (R_BUFFER_BYTES, &u);
135 }
136 
r_buf_new_empty(ut64 len)137 R_API RBuffer *r_buf_new_empty(ut64 len) {
138 	ut8 *buf = R_NEWS0 (ut8, len);
139 	if (!buf) {
140 		return NULL;
141 	}
142 
143 	struct buf_bytes_user u = { 0 };
144 	u.data_steal = buf;
145 	u.length = len;
146 	u.steal = true;
147 	RBuffer *res = new_buffer (R_BUFFER_BYTES, &u);
148 	if (!res) {
149 		free (buf);
150 	}
151 	return res;
152 }
153 
r_buf_new_with_bytes(const ut8 * bytes,ut64 len)154 R_API RBuffer *r_buf_new_with_bytes(const ut8 *bytes, ut64 len) {
155 	struct buf_bytes_user u = { 0 };
156 	u.data = bytes;
157 	u.length = len;
158 	return new_buffer (R_BUFFER_BYTES, &u);
159 }
160 
r_buf_new_slice(RBuffer * b,ut64 offset,ut64 size)161 R_API RBuffer *r_buf_new_slice(RBuffer *b, ut64 offset, ut64 size) {
162 	struct buf_ref_user u = { 0 };
163 	u.parent = b;
164 	u.offset = offset;
165 	u.size = size;
166 	return new_buffer (R_BUFFER_REF, &u);
167 }
168 
r_buf_new_with_string(const char * msg)169 R_API RBuffer *r_buf_new_with_string(const char *msg) {
170 	return r_buf_new_with_bytes ((const ut8 *)msg, (ut64)strlen (msg));
171 }
172 
r_buf_new_with_buf(RBuffer * b)173 R_API RBuffer *r_buf_new_with_buf(RBuffer *b) {
174 	ut64 sz = 0;
175 	const ut8 *tmp = r_buf_data (b, &sz);
176 	return r_buf_new_with_bytes (tmp, sz);
177 }
178 
r_buf_new_sparse(ut8 Oxff)179 R_API RBuffer *r_buf_new_sparse(ut8 Oxff) {
180 	RBuffer *b = new_buffer (R_BUFFER_SPARSE, NULL);
181 	if (b) {
182 		b->Oxff_priv = Oxff;
183 	}
184 	return b;
185 }
186 
r_buf_new(void)187 R_API RBuffer *r_buf_new(void) {
188 	struct buf_bytes_user u = { 0 };
189 	u.data = NULL;
190 	u.length = 0;
191 	return new_buffer (R_BUFFER_BYTES, &u);
192 }
193 
r_buf_data(RBuffer * b,ut64 * size)194 R_DEPRECATE R_API const ut8 *r_buf_data(RBuffer *b, ut64 *size) {
195 	r_return_val_if_fail (b, NULL);
196 	b->whole_buf = get_whole_buf (b, size);
197 	return b->whole_buf;
198 }
199 
r_buf_size(RBuffer * b)200 R_API ut64 r_buf_size(RBuffer *b) {
201 	r_return_val_if_fail (b, 0);
202 	return buf_get_size (b);
203 }
204 
205 // rename to new?
r_buf_new_mmap(const char * filename,int perm)206 R_API RBuffer *r_buf_new_mmap(const char *filename, int perm) {
207 	r_return_val_if_fail (filename, NULL);
208 	struct buf_mmap_user u = { 0 };
209 	u.filename = filename;
210 	u.perm = perm;
211 	return new_buffer (R_BUFFER_MMAP, &u);
212 }
213 
r_buf_new_file(const char * file,int perm,int mode)214 R_API RBuffer *r_buf_new_file(const char *file, int perm, int mode) {
215 	struct buf_file_user u = { 0 };
216 	u.file = file;
217 	u.perm = perm;
218 	u.mode = mode;
219 	return new_buffer (R_BUFFER_FILE, &u);
220 }
221 
222 // TODO: rename to new_from_file ?
r_buf_new_slurp(const char * file)223 R_API RBuffer *r_buf_new_slurp(const char *file) {
224 	size_t len;
225 	char *tmp = r_file_slurp (file, &len);
226 	if (!tmp) {
227 		return NULL;
228 	}
229 
230 	struct buf_bytes_user u = { 0 };
231 	u.data_steal = (ut8 *)tmp;
232 	u.length = (ut64)len;
233 	u.steal = true;
234 	return new_buffer (R_BUFFER_BYTES, &u);
235 }
236 
r_buf_dump(RBuffer * b,const char * file)237 R_API bool r_buf_dump(RBuffer *b, const char *file) {
238 	// TODO: need to redo this
239 	if (!b || !file) {
240 		return false;
241 	}
242 	ut64 tmpsz = 0;
243 	const ut8 *tmp = r_buf_data (b, &tmpsz);
244 	return r_file_dump (file, tmp, tmpsz, 0);
245 }
246 
r_buf_seek(RBuffer * b,st64 addr,int whence)247 R_API st64 r_buf_seek(RBuffer *b, st64 addr, int whence) {
248 	r_return_val_if_fail (b, -1);
249 	return buf_seek (b, addr, whence);
250 }
251 
r_buf_tell(RBuffer * b)252 R_API ut64 r_buf_tell(RBuffer *b) {
253 	return r_buf_seek (b, 0, R_BUF_CUR);
254 }
255 
r_buf_set_bytes(RBuffer * b,const ut8 * buf,ut64 length)256 R_API bool r_buf_set_bytes(RBuffer *b, const ut8 *buf, ut64 length) {
257 	r_return_val_if_fail (b && buf && !b->readonly, false);
258 	if (!r_buf_resize (b, 0)) {
259 		return false;
260 	}
261 	if (r_buf_seek (b, 0, R_BUF_SET) < 0) {
262 		return false;
263 	}
264 	if (!r_buf_append_bytes (b, buf, length)) {
265 		return false;
266 	}
267 	return r_buf_seek (b, 0, R_BUF_SET) >= 0;
268 }
269 
r_buf_prepend_bytes(RBuffer * b,const ut8 * buf,ut64 length)270 R_API bool r_buf_prepend_bytes(RBuffer *b, const ut8 *buf, ut64 length) {
271 	r_return_val_if_fail (b && buf && !b->readonly, false);
272 	return r_buf_insert_bytes (b, 0, buf, length) >= 0;
273 }
274 
r_buf_to_string(RBuffer * b)275 R_API char *r_buf_to_string(RBuffer *b) {
276 	ut64 sz = r_buf_size (b);
277 	char *s = malloc (sz + 1);
278 	if (!s) {
279 		return NULL;
280 	}
281 	if (r_buf_read_at (b, 0, (ut8 *)s, sz) < 0) {
282 		free (s);
283 		return NULL;
284 	}
285 	s[sz] = '\0';
286 	return s;
287 }
288 
r_buf_append_bytes(RBuffer * b,const ut8 * buf,ut64 length)289 R_API bool r_buf_append_bytes(RBuffer *b, const ut8 *buf, ut64 length) {
290 	r_return_val_if_fail (b && buf && !b->readonly, false);
291 
292 	if (r_buf_seek (b, 0, R_BUF_END) < 0) {
293 		return false;
294 	}
295 
296 	return r_buf_write (b, buf, length) >= 0;
297 }
298 
r_buf_append_nbytes(RBuffer * b,ut64 length)299 R_API bool r_buf_append_nbytes(RBuffer *b, ut64 length) {
300 	r_return_val_if_fail (b && !b->readonly, false);
301 	ut8 *buf = R_NEWS0 (ut8, length);
302 	if (!buf) {
303 		return false;
304 	}
305 	bool res = r_buf_append_bytes (b, buf, length);
306 	free (buf);
307 	return res;
308 }
309 
r_buf_insert_bytes(RBuffer * b,ut64 addr,const ut8 * buf,ut64 length)310 R_API st64 r_buf_insert_bytes(RBuffer *b, ut64 addr, const ut8 *buf, ut64 length) {
311 	r_return_val_if_fail (b && !b->readonly, -1);
312 	st64 pos, r = r_buf_seek (b, 0, R_BUF_CUR);
313 	if (r < 0) {
314 		return r;
315 	}
316 	pos = r;
317 	r = r_buf_seek (b, addr, R_BUF_SET);
318 	if (r < 0) {
319 		goto restore_pos;
320 	}
321 
322 	ut64 sz = r_buf_size (b);
323 	ut8 *tmp = R_NEWS (ut8, sz - addr);
324 	r = r_buf_read (b, tmp, sz - addr);
325 	if (r < 0) {
326 		goto free_tmp;
327 	}
328 	st64 tmp_length = r;
329 	if (!r_buf_resize (b, sz + length)) {
330 		goto free_tmp;
331 	}
332 	r = r_buf_seek (b, addr + length, R_BUF_SET);
333 	if (r < 0) {
334 		goto free_tmp;
335 	}
336 	r = r_buf_write (b, tmp, tmp_length);
337 	if (r < 0) {
338 		goto free_tmp;
339 	}
340 	r = r_buf_seek (b, addr, R_BUF_SET);
341 	if (r < 0) {
342 		goto free_tmp;
343 	}
344 	r = r_buf_write (b, buf, length);
345 free_tmp:
346 	free (tmp);
347 restore_pos:
348 	r_buf_seek (b, pos, R_BUF_SET);
349 	return r;
350 }
351 
r_buf_append_ut16(RBuffer * b,ut16 n)352 R_API bool r_buf_append_ut16(RBuffer *b, ut16 n) {
353 	r_return_val_if_fail (b && !b->readonly, false);
354 	return r_buf_append_bytes (b, (const ut8 *)&n, sizeof (n));
355 }
356 
r_buf_append_ut32(RBuffer * b,ut32 n)357 R_API bool r_buf_append_ut32(RBuffer *b, ut32 n) {
358 	r_return_val_if_fail (b && !b->readonly, false);
359 	return r_buf_append_bytes (b, (const ut8 *)&n, sizeof (n));
360 }
361 
r_buf_append_ut64(RBuffer * b,ut64 n)362 R_API bool r_buf_append_ut64(RBuffer *b, ut64 n) {
363 	r_return_val_if_fail (b && !b->readonly, false);
364 	return r_buf_append_bytes (b, (const ut8 *)&n, sizeof (n));
365 }
366 
r_buf_append_buf(RBuffer * b,RBuffer * a)367 R_API bool r_buf_append_buf(RBuffer *b, RBuffer *a) {
368 	r_return_val_if_fail (b && a && !b->readonly, false);
369 	ut64 sz = 0;
370 	const ut8 *tmp = r_buf_data (a, &sz);
371 	return r_buf_append_bytes (b, tmp, sz);
372 }
373 
r_buf_append_buf_slice(RBuffer * b,RBuffer * a,ut64 offset,ut64 size)374 R_API bool r_buf_append_buf_slice(RBuffer *b, RBuffer *a, ut64 offset, ut64 size) {
375 	r_return_val_if_fail (b && a && !b->readonly, false);
376 	ut8 *tmp = R_NEWS (ut8, size);
377 	bool res = false;
378 
379 	if (!tmp) {
380 		return false;
381 	}
382 	st64 r = r_buf_read_at (a, offset, tmp, size);
383 	if (r < 0) {
384 		goto err;
385 	}
386 	res = r_buf_append_bytes (b, tmp, r);
387 err:
388 	free (tmp);
389 	return res;
390 }
391 
392 // return an heap-allocated string read from the RBuffer b at address addr. The
393 // length depends on the first '\0' found in the buffer. If there is no '\0' in
394 // the buffer, there is no string, thus NULL is returned.
r_buf_get_string(RBuffer * b,ut64 addr)395 R_API char *r_buf_get_string(RBuffer *b, ut64 addr) {
396 	const int MIN_RES_SZ = 64;
397 	ut8 *res = R_NEWS (ut8, MIN_RES_SZ + 1);
398 	ut64 sz = 0;
399 	st64 r = r_buf_read_at (b, addr, res, MIN_RES_SZ);
400 	bool null_found = false;
401 	while (r > 0) {
402 		const ut8 *needle = r_mem_mem (res + sz, r, (ut8 *)"\x00", 1);
403 		if (needle) {
404 			null_found = true;
405 			break;
406 		}
407 		sz += r;
408 		addr += r;
409 
410 		ut8 *restmp = realloc (res, sz + MIN_RES_SZ + 1);
411 		if (!restmp) {
412 			free (res);
413 			return NULL;
414 		}
415 		res = restmp;
416 		r = r_buf_read_at (b, addr, res + sz, MIN_RES_SZ);
417 	}
418 	if (r < 0 || !null_found) {
419 		free (res);
420 		return NULL;
421 	}
422 	return (char *)res;
423 }
424 
r_buf_read(RBuffer * b,ut8 * buf,ut64 len)425 R_API st64 r_buf_read(RBuffer *b, ut8 *buf, ut64 len) {
426 	r_return_val_if_fail (b && buf, -1);
427 	st64 r = buf_read (b, buf, len);
428 	if (r >= 0 && r < len) {
429 		memset (buf + r, b->Oxff_priv, len - r);
430 	}
431 	return r;
432 }
433 
r_buf_write(RBuffer * b,const ut8 * buf,ut64 len)434 R_API st64 r_buf_write(RBuffer *b, const ut8 *buf, ut64 len) {
435 	r_return_val_if_fail (b && buf && !b->readonly, -1);
436 	return buf_write (b, buf, len);
437 }
438 
r_buf_read8(RBuffer * b)439 R_API ut8 r_buf_read8(RBuffer *b) {
440 	ut8 res;
441 	st64 r = r_buf_read (b, &res, sizeof (res));
442 	return r == sizeof (res)? res: b->Oxff_priv;
443 }
444 
r_buf_read8_at(RBuffer * b,ut64 addr)445 R_API ut8 r_buf_read8_at(RBuffer *b, ut64 addr) {
446 	ut8 res;
447 	st64 r = r_buf_read_at (b, addr, &res, sizeof (res));
448 	return r == sizeof (res)? res: b->Oxff_priv;
449 }
450 
buf_format(RBuffer * dst,RBuffer * src,const char * fmt,int n)451 static st64 buf_format(RBuffer *dst, RBuffer *src, const char *fmt, int n) {
452 	st64 res = 0;
453 	int i;
454 	for (i = 0; i < n; i++) {
455 		int j;
456 		int m = 1;
457 		int tsize = 2;
458 		bool bigendian = true;
459 
460 		for (j = 0; fmt[j]; j++) {
461 			switch (fmt[j]) {
462 			case '0':
463 			case '1':
464 			case '2':
465 			case '3':
466 			case '4':
467 			case '5':
468 			case '6':
469 			case '7':
470 			case '8':
471 			case '9':
472 				if (m == 1) {
473 					m = r_num_get (NULL, &fmt[j]);
474 				}
475 				continue;
476 			case 's': tsize = 2; bigendian = false; break;
477 			case 'S': tsize = 2; bigendian = true; break;
478 			case 'i': tsize = 4; bigendian = false; break;
479 			case 'I': tsize = 4; bigendian = true; break;
480 			case 'l': tsize = 8; bigendian = false; break;
481 			case 'L': tsize = 8; bigendian = true; break;
482 			case 'c': tsize = 1; bigendian = false; break;
483 			default: return -1;
484 			}
485 
486 			int k;
487 			for (k = 0; k < m; k++) {
488 				ut8 tmp[sizeof (ut64)];
489 				ut8 d1;
490 				ut16 d2;
491 				ut32 d3;
492 				ut64 d4;
493 				st64 r = r_buf_read (src, tmp, tsize);
494 				if (r < tsize) {
495 					return -1;
496 				}
497 
498 				switch (tsize) {
499 				case 1:
500 					d1 = r_read_ble8 (tmp);
501 					r = r_buf_write (dst, (ut8 *)&d1, 1);
502 					break;
503 				case 2:
504 					d2 = r_read_ble16 (tmp, bigendian);
505 					r = r_buf_write (dst, (ut8 *)&d2, 2);
506 					break;
507 				case 4:
508 					d3 = r_read_ble32 (tmp, bigendian);
509 					r = r_buf_write (dst, (ut8 *)&d3, 4);
510 					break;
511 				case 8:
512 					d4 = r_read_ble64 (tmp, bigendian);
513 					r = r_buf_write (dst, (ut8 *)&d4, 8);
514 					break;
515 				}
516 				if (r < 0) {
517 					return -1;
518 				}
519 				res += r;
520 			}
521 
522 			m = 1;
523 			bigendian = true;
524 		}
525 	}
526 	return res;
527 }
528 
r_buf_fread(RBuffer * b,ut8 * buf,const char * fmt,int n)529 R_API st64 r_buf_fread(RBuffer *b, ut8 *buf, const char *fmt, int n) {
530 	r_return_val_if_fail (b && buf && fmt, -1);
531 	// XXX: we assume the caller knows what he's doing
532 	RBuffer *dst = r_buf_new_with_pointers (buf, UT64_MAX, false);
533 	st64 res = buf_format (dst, b, fmt, n);
534 	r_buf_free (dst);
535 	return res;
536 }
537 
r_buf_fread_at(RBuffer * b,ut64 addr,ut8 * buf,const char * fmt,int n)538 R_API st64 r_buf_fread_at(RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n) {
539 	r_return_val_if_fail (b && buf && fmt, -1);
540 	st64 o_addr = r_buf_seek (b, 0, R_BUF_CUR);
541 	int r = r_buf_seek (b, addr, R_BUF_SET);
542 	if (r < 0) {
543 		return r;
544 	}
545 	r = r_buf_fread (b, buf, fmt, n);
546 	r_buf_seek (b, o_addr, R_BUF_SET);
547 	return r;
548 }
549 
r_buf_fwrite(RBuffer * b,const ut8 * buf,const char * fmt,int n)550 R_API st64 r_buf_fwrite(RBuffer *b, const ut8 *buf, const char *fmt, int n) {
551 	r_return_val_if_fail (b && buf && fmt && !b->readonly, -1);
552 	// XXX: we assume the caller knows what he's doing
553 	RBuffer *src = r_buf_new_with_pointers (buf, UT64_MAX, false);
554 	st64 res = buf_format (b, src, fmt, n);
555 	r_buf_free (src);
556 	return res;
557 }
558 
r_buf_fwrite_at(RBuffer * b,ut64 addr,const ut8 * buf,const char * fmt,int n)559 R_API st64 r_buf_fwrite_at(RBuffer *b, ut64 addr, const ut8 *buf, const char *fmt, int n) {
560 	r_return_val_if_fail (b && buf && fmt && !b->readonly, -1);
561 	st64 o_addr = r_buf_seek (b, 0, R_BUF_CUR);
562 	st64 r = r_buf_seek (b, addr, R_BUF_SET);
563 	if (r < 0) {
564 		return r;
565 	}
566 	r = r_buf_fwrite (b, buf, fmt, n);
567 	r_buf_seek (b, o_addr, R_BUF_SET);
568 	return r;
569 }
570 
r_buf_read_at(RBuffer * b,ut64 addr,ut8 * buf,ut64 len)571 R_API st64 r_buf_read_at(RBuffer *b, ut64 addr, ut8 *buf, ut64 len) {
572 	r_return_val_if_fail (b && buf, -1);
573 	st64 o_addr = r_buf_seek (b, 0, R_BUF_CUR);
574 	st64 r = r_buf_seek (b, addr, R_BUF_SET);
575 	if (r < 0) {
576 		return r;
577 	}
578 
579 	r = r_buf_read (b, buf, len);
580 	r_buf_seek (b, o_addr, R_BUF_SET);
581 	return r;
582 }
583 
r_buf_write_at(RBuffer * b,ut64 addr,const ut8 * buf,ut64 len)584 R_API st64 r_buf_write_at(RBuffer *b, ut64 addr, const ut8 *buf, ut64 len) {
585 	r_return_val_if_fail (b && buf && !b->readonly, -1);
586 	st64 o_addr = r_buf_seek (b, 0, R_BUF_CUR);
587 	st64 r = r_buf_seek (b, addr, R_BUF_SET);
588 	if (r < 0) {
589 		return r;
590 	}
591 
592 	r = r_buf_write (b, buf, len);
593 	r_buf_seek (b, o_addr, R_BUF_SET);
594 	return r;
595 }
596 
r_buf_fini(RBuffer * b)597 R_API bool r_buf_fini(RBuffer *b) {
598 	if (!b) {
599 		return false;
600 	}
601 	if (b->refctr > 0) {
602 		b->refctr--;
603 		return false;
604 	}
605 
606 	// free the whole_buf only if it was initially allocated by the buf types
607 	if (b->methods->get_whole_buf) {
608 		if (b->methods->free_whole_buf) {
609 			b->methods->free_whole_buf (b);
610 		}
611 	} else {
612 		R_FREE (b->whole_buf);
613 	}
614 	return buf_fini (b);
615 }
616 
r_buf_free(RBuffer * b)617 R_API void r_buf_free(RBuffer *b) {
618 	if (r_buf_fini (b)) {
619 		free (b);
620 	}
621 }
622 
r_buf_append_string(RBuffer * b,const char * str)623 R_API st64 r_buf_append_string(RBuffer *b, const char *str) {
624 	r_return_val_if_fail (b && str && !b->readonly, false);
625 	return r_buf_append_bytes (b, (const ut8 *)str, strlen (str));
626 }
627 
r_buf_resize(RBuffer * b,ut64 newsize)628 R_API bool r_buf_resize(RBuffer *b, ut64 newsize) {
629 	r_return_val_if_fail (b, false);
630 	return buf_resize (b, newsize);
631 }
632 
r_buf_ref(RBuffer * b)633 R_API RBuffer *r_buf_ref(RBuffer *b) {
634 	if (b) {
635 		b->refctr++;
636 	}
637 	return b;
638 }
639 
r_buf_nonempty_list(RBuffer * b)640 R_API RList *r_buf_nonempty_list(RBuffer *b) {
641 	return b->methods->nonempty_list? b->methods->nonempty_list (b): NULL;
642 }
643 
r_buf_uleb128(RBuffer * b,ut64 * v)644 R_API st64 r_buf_uleb128(RBuffer *b, ut64 *v) {
645 	ut8 c = 0xff;
646 	ut64 s = 0, sum = 0, l = 0;
647 	do {
648 		ut8 data;
649 		st64 r = r_buf_read (b, &data, sizeof (data));
650 		if (r < 1) {
651 			return -1;
652 		}
653 		c = data & 0xff;
654 		if (s < 64) {
655 			sum |= ((ut64) (c & 0x7f) << s);
656 			s += 7;
657 		} else {
658 			sum = 0;
659 		}
660 		l++;
661 	} while (c & 0x80);
662 	if (v) {
663 		*v = sum;
664 	}
665 	return l;
666 }
667 
r_buf_sleb128(RBuffer * b,st64 * v)668 R_API st64 r_buf_sleb128(RBuffer *b, st64 *v) {
669 	st64 result = 0, offset = 0;
670 	ut8 value;
671 	do {
672 		st64 chunk;
673 		st64 r = r_buf_read (b, &value, sizeof (value));
674 		if (r != sizeof (value)) {
675 			return -1;
676 		}
677 		chunk = value & 0x7f;
678 		if (offset < 64) {
679 			result |= (chunk << offset);
680 			offset += 7;
681 		} else {
682 			result = 0;
683 		}
684 	} while (value & 0x80);
685 
686 	if ((value & 0x40) != 0) {
687 		if (offset < 64) {
688 			result |= ~0ULL << offset;
689 		}
690 	}
691 	if (v) {
692 		*v = result;
693 	}
694 	return offset / 7;
695 }
696