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