2 * Copyright © 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 #include "main/macros.h"
37 #define BLOB_INITIAL_SIZE 4096
39 /* Ensure that \blob will be able to fit an additional object of size
40 * \additional. The growing (if any) will occur by doubling the existing
44 grow_to_fit(struct blob
*blob
, size_t additional
)
49 if (blob
->out_of_memory
)
52 if (blob
->size
+ additional
<= blob
->allocated
)
55 if (blob
->fixed_allocation
) {
56 blob
->out_of_memory
= true;
60 if (blob
->allocated
== 0)
61 to_allocate
= BLOB_INITIAL_SIZE
;
63 to_allocate
= blob
->allocated
* 2;
65 to_allocate
= MAX2(to_allocate
, blob
->allocated
+ additional
);
67 new_data
= realloc(blob
->data
, to_allocate
);
68 if (new_data
== NULL
) {
69 blob
->out_of_memory
= true;
73 blob
->data
= new_data
;
74 blob
->allocated
= to_allocate
;
79 /* Align the blob->size so that reading or writing a value at (blob->data +
80 * blob->size) will result in an access aligned to a granularity of \alignment
83 * \return True unless allocation fails
86 align_blob(struct blob
*blob
, size_t alignment
)
88 const size_t new_size
= ALIGN(blob
->size
, alignment
);
90 if (blob
->size
< new_size
) {
91 if (!grow_to_fit(blob
, new_size
- blob
->size
))
95 memset(blob
->data
+ blob
->size
, 0, new_size
- blob
->size
);
96 blob
->size
= new_size
;
103 align_blob_reader(struct blob_reader
*blob
, size_t alignment
)
105 blob
->current
= blob
->data
+ ALIGN(blob
->current
- blob
->data
, alignment
);
109 blob_init(struct blob
*blob
)
114 blob
->fixed_allocation
= false;
115 blob
->out_of_memory
= false;
119 blob_init_fixed(struct blob
*blob
, void *data
, size_t size
)
122 blob
->allocated
= size
;
124 blob
->fixed_allocation
= true;
125 blob
->out_of_memory
= false;
129 blob_overwrite_bytes(struct blob
*blob
,
134 /* Detect an attempt to overwrite data out of bounds. */
135 if (offset
+ to_write
< offset
|| blob
->size
< offset
+ to_write
)
138 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
141 memcpy(blob
->data
+ offset
, bytes
, to_write
);
147 blob_write_bytes(struct blob
*blob
, const void *bytes
, size_t to_write
)
149 if (! grow_to_fit(blob
, to_write
))
152 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
155 memcpy(blob
->data
+ blob
->size
, bytes
, to_write
);
156 blob
->size
+= to_write
;
162 blob_reserve_bytes(struct blob
*blob
, size_t to_write
)
166 if (! grow_to_fit (blob
, to_write
))
170 blob
->size
+= to_write
;
176 blob_reserve_uint32(struct blob
*blob
)
178 align_blob(blob
, sizeof(uint32_t));
179 return blob_reserve_bytes(blob
, sizeof(uint32_t));
183 blob_reserve_intptr(struct blob
*blob
)
185 align_blob(blob
, sizeof(intptr_t));
186 return blob_reserve_bytes(blob
, sizeof(intptr_t));
190 blob_write_uint32(struct blob
*blob
, uint32_t value
)
192 align_blob(blob
, sizeof(value
));
194 return blob_write_bytes(blob
, &value
, sizeof(value
));
197 #define ASSERT_ALIGNED(_offset, _align) \
198 assert(ALIGN((_offset), (_align)) == (_offset))
201 blob_overwrite_uint32 (struct blob
*blob
,
205 ASSERT_ALIGNED(offset
, sizeof(value
));
206 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
210 blob_write_uint64(struct blob
*blob
, uint64_t value
)
212 align_blob(blob
, sizeof(value
));
214 return blob_write_bytes(blob
, &value
, sizeof(value
));
218 blob_write_intptr(struct blob
*blob
, intptr_t value
)
220 align_blob(blob
, sizeof(value
));
222 return blob_write_bytes(blob
, &value
, sizeof(value
));
226 blob_overwrite_intptr (struct blob
*blob
,
230 ASSERT_ALIGNED(offset
, sizeof(value
));
231 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
235 blob_write_string(struct blob
*blob
, const char *str
)
237 return blob_write_bytes(blob
, str
, strlen(str
) + 1);
241 blob_reader_init(struct blob_reader
*blob
, const void *data
, size_t size
)
244 blob
->end
= blob
->data
+ size
;
245 blob
->current
= data
;
246 blob
->overrun
= false;
249 /* Check that an object of size \size can be read from this blob.
251 * If not, set blob->overrun to indicate that we attempted to read too far.
254 ensure_can_read(struct blob_reader
*blob
, size_t size
)
259 if (blob
->current
<= blob
->end
&& blob
->end
- blob
->current
>= size
)
262 blob
->overrun
= true;
268 blob_read_bytes(struct blob_reader
*blob
, size_t size
)
272 if (! ensure_can_read (blob
, size
))
277 blob
->current
+= size
;
283 blob_copy_bytes(struct blob_reader
*blob
, void *dest
, size_t size
)
287 bytes
= blob_read_bytes(blob
, size
);
291 memcpy(dest
, bytes
, size
);
294 /* These next three read functions have identical form. If we add any beyond
295 * these first three we should probably switch to generating these with a
296 * preprocessor macro.
299 blob_read_uint32(struct blob_reader
*blob
)
302 int size
= sizeof(ret
);
304 align_blob_reader(blob
, size
);
306 if (! ensure_can_read(blob
, size
))
309 ret
= *((uint32_t*) blob
->current
);
311 blob
->current
+= size
;
317 blob_read_uint64(struct blob_reader
*blob
)
320 int size
= sizeof(ret
);
322 align_blob_reader(blob
, size
);
324 if (! ensure_can_read(blob
, size
))
327 ret
= *((uint64_t*) blob
->current
);
329 blob
->current
+= size
;
335 blob_read_intptr(struct blob_reader
*blob
)
338 int size
= sizeof(ret
);
340 align_blob_reader(blob
, size
);
342 if (! ensure_can_read(blob
, size
))
345 ret
= *((intptr_t *) blob
->current
);
347 blob
->current
+= size
;
353 blob_read_string(struct blob_reader
*blob
)
359 /* If we're already at the end, then this is an overrun. */
360 if (blob
->current
>= blob
->end
) {
361 blob
->overrun
= true;
365 /* Similarly, if there is no zero byte in the data remaining in this blob,
366 * we also consider that an overrun.
368 nul
= memchr(blob
->current
, 0, blob
->end
- blob
->current
);
371 blob
->overrun
= true;
375 size
= nul
- blob
->current
+ 1;
377 assert(ensure_can_read(blob
, size
));
379 ret
= (char *) blob
->current
;
381 blob
->current
+= size
;