1 /* radare - LGPL - Copyright 2009-2020 - ret2libc */
2
3 #include <r_util.h>
4
5 struct buf_sparse_priv {
6 RList *sparse;
7 ut64 offset;
8 };
9
buffer_sparse_free(void * a)10 static void buffer_sparse_free(void *a) {
11 RBufferSparse *s = (RBufferSparse *)a;
12 free (s->data);
13 free (s);
14 }
15
sparse_limits(RList * l,ut64 * max)16 static bool sparse_limits(RList *l, ut64 *max) {
17 bool set = false;
18 RBufferSparse *s;
19 RListIter *iter;
20
21 r_list_foreach (l, iter, s) {
22 if (set) {
23 if (max && s->to > *max) {
24 *max = s->to;
25 }
26 } else {
27 set = true;
28 if (max) {
29 *max = s->to;
30 }
31 }
32 }
33 return set;
34 }
35
sparse_append(RList * l,ut64 addr,const ut8 * data,ut64 len)36 static RBufferSparse *sparse_append(RList *l, ut64 addr, const ut8 *data, ut64 len) {
37 if (l && data) {
38 RBufferSparse *s = R_NEW0 (RBufferSparse);
39 if (s) {
40 s->data = calloc (1, len);
41 if (s->data) {
42 s->from = addr;
43 s->to = addr + len;
44 s->size = len;
45 memcpy (s->data, data, len);
46 return r_list_append (l, s)? s: NULL;
47 }
48 free (s);
49 }
50 }
51 return NULL;
52 }
53
54 //ret -1 if failed; # of bytes copied if success
sparse_write(RList * l,ut64 addr,const ut8 * data,ut64 len)55 static st64 sparse_write(RList *l, ut64 addr, const ut8 *data, ut64 len) {
56 RBufferSparse *s;
57 RListIter *iter;
58 ut64 olen = len;
59
60 r_list_foreach (l, iter, s) {
61 if (addr >= s->from && addr < s->to) {
62 ut64 delta = addr - s->from;
63 ut64 reallen = s->size - delta >= len? len: s->size - delta;
64 memcpy (s->data + delta, data, reallen);
65 data += reallen;
66 len -= reallen;
67 addr += reallen;
68 }
69 if (len == 0) {
70 return olen;
71 }
72 }
73 if (len > 0 && !sparse_append (l, addr, data, len)) {
74 return -1;
75 }
76 return olen;
77 }
78
get_priv_sparse(RBuffer * b)79 static inline struct buf_sparse_priv *get_priv_sparse(RBuffer *b) {
80 struct buf_sparse_priv *priv = (struct buf_sparse_priv *)b->priv;
81 r_warn_if_fail (priv);
82 return priv;
83 }
84
buf_sparse_init(RBuffer * b,const void * user)85 static bool buf_sparse_init(RBuffer *b, const void *user) {
86 struct buf_sparse_priv *priv = R_NEW0 (struct buf_sparse_priv);
87 if (!priv) {
88 return false;
89 }
90 priv->sparse = r_list_newf (buffer_sparse_free);
91 priv->offset = 0;
92 b->priv = priv;
93 return true;
94 }
95
buf_sparse_fini(RBuffer * b)96 static bool buf_sparse_fini(RBuffer *b) {
97 struct buf_sparse_priv *priv = get_priv_sparse (b);
98 r_list_free (priv->sparse);
99 R_FREE (b->priv);
100 return true;
101 }
102
buf_sparse_resize(RBuffer * b,ut64 newsize)103 static bool buf_sparse_resize(RBuffer *b, ut64 newsize) {
104 struct buf_sparse_priv *priv = get_priv_sparse (b);
105 RListIter *iter, *tmp;
106 RBufferSparse *s;
107
108 r_list_foreach_safe (priv->sparse, iter, tmp, s) {
109 if (s->from >= newsize) {
110 r_list_delete (priv->sparse, iter);
111 } else if (s->to >= newsize) {
112 RBufferSparse *ns = R_NEW (RBufferSparse);
113 ns->from = s->from;
114 ns->to = newsize;
115 ns->size = ns->to - ns->from;
116 ut8 *tmp = realloc (s->data, s->size);
117 if (!tmp) {
118 free (ns);
119 return false;
120 }
121 // otherwise it will be double-freed by r_list_delete
122 s->data = NULL;
123 ns->data = tmp;
124 ns->written = s->written;
125 r_list_append (priv->sparse, ns);
126 r_list_delete (priv->sparse, iter);
127 }
128 }
129 ut64 max;
130 max = sparse_limits (priv->sparse, &max)? max: 0;
131 if (max < newsize) {
132 return !!sparse_write (priv->sparse, newsize - 1, &b->Oxff_priv, 1);
133 }
134 return true;
135 }
136
buf_sparse_size(RBuffer * b)137 static ut64 buf_sparse_size(RBuffer *b) {
138 struct buf_sparse_priv *priv = get_priv_sparse (b);
139 ut64 max;
140
141 return sparse_limits (priv->sparse, &max)? max: 0;
142 }
143
buf_sparse_read(RBuffer * b,ut8 * buf,ut64 len)144 static st64 buf_sparse_read(RBuffer *b, ut8 *buf, ut64 len) {
145 struct buf_sparse_priv *priv = get_priv_sparse (b);
146 RBufferSparse *c;
147 RListIter *iter;
148 ut64 max = 0;
149
150 memset (buf, b->Oxff_priv, len);
151 r_list_foreach (priv->sparse, iter, c) {
152 if (max < c->to) {
153 max = c->to;
154 }
155 if (priv->offset < c->to && c->from < priv->offset + len) {
156 if (priv->offset < c->from) {
157 ut64 l = R_MIN (priv->offset + len - c->from, c->size);
158 memcpy (buf + c->from - priv->offset, c->data, l);
159 } else {
160 ut64 l = R_MIN (c->to - priv->offset, len);
161 memcpy (buf, c->data + priv->offset - c->from, l);
162 }
163 }
164 }
165 if (priv->offset > max) {
166 return -1;
167 }
168 ut64 r = R_MIN (max - priv->offset, len);
169 priv->offset += r;
170 return r;
171 }
172
buf_sparse_write(RBuffer * b,const ut8 * buf,ut64 len)173 static st64 buf_sparse_write(RBuffer *b, const ut8 *buf, ut64 len) {
174 struct buf_sparse_priv *priv = get_priv_sparse (b);
175 st64 r = sparse_write (priv->sparse, priv->offset, buf, len);
176 priv->offset += r;
177 return r;
178 }
179
buf_sparse_seek(RBuffer * b,st64 addr,int whence)180 static st64 buf_sparse_seek(RBuffer *b, st64 addr, int whence) {
181 struct buf_sparse_priv *priv = get_priv_sparse (b);
182 ut64 max;
183 if (addr < 0 && (-addr) > (st64)priv->offset) {
184 return -1;
185 }
186
187 switch (whence) {
188 case R_BUF_CUR:
189 priv->offset += addr;
190 break;
191 case R_BUF_SET:
192 priv->offset = addr;
193 break;
194 case R_BUF_END:
195 if (!sparse_limits (priv->sparse, &max)) {
196 max = 0;
197 }
198 priv->offset = max + addr;
199 break;
200 default:
201 r_warn_if_reached ();
202 return -1;
203 }
204 return priv->offset;
205 }
206
buf_sparse_nonempty_list(RBuffer * b)207 static RList *buf_sparse_nonempty_list(RBuffer *b) {
208 struct buf_sparse_priv *priv = get_priv_sparse (b);
209 return r_list_clone (priv->sparse);
210 }
211
212 static const RBufferMethods buffer_sparse_methods = {
213 .init = buf_sparse_init,
214 .fini = buf_sparse_fini,
215 .read = buf_sparse_read,
216 .write = buf_sparse_write,
217 .get_size = buf_sparse_size,
218 .resize = buf_sparse_resize,
219 .seek = buf_sparse_seek,
220 .nonempty_list = buf_sparse_nonempty_list,
221 };
222