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_finish_get_buffer(struct blob
*blob
, void **buffer
, size_t *size
)
131 *buffer
= blob
->data
;
135 /* Trim the buffer. */
136 *buffer
= realloc(*buffer
, *size
);
140 blob_overwrite_bytes(struct blob
*blob
,
145 /* Detect an attempt to overwrite data out of bounds. */
146 if (offset
+ to_write
< offset
|| blob
->size
< offset
+ to_write
)
149 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
152 memcpy(blob
->data
+ offset
, bytes
, to_write
);
158 blob_write_bytes(struct blob
*blob
, const void *bytes
, size_t to_write
)
160 if (! grow_to_fit(blob
, to_write
))
163 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
165 if (blob
->data
&& to_write
> 0)
166 memcpy(blob
->data
+ blob
->size
, bytes
, to_write
);
167 blob
->size
+= to_write
;
173 blob_reserve_bytes(struct blob
*blob
, size_t to_write
)
177 if (! grow_to_fit (blob
, to_write
))
181 blob
->size
+= to_write
;
187 blob_reserve_uint32(struct blob
*blob
)
189 align_blob(blob
, sizeof(uint32_t));
190 return blob_reserve_bytes(blob
, sizeof(uint32_t));
194 blob_reserve_intptr(struct blob
*blob
)
196 align_blob(blob
, sizeof(intptr_t));
197 return blob_reserve_bytes(blob
, sizeof(intptr_t));
200 #define BLOB_WRITE_TYPE(name, type) \
202 name(struct blob *blob, type value) \
204 align_blob(blob, sizeof(value)); \
205 return blob_write_bytes(blob, &value, sizeof(value)); \
208 BLOB_WRITE_TYPE(blob_write_uint8
, uint8_t)
209 BLOB_WRITE_TYPE(blob_write_uint16
, uint16_t)
210 BLOB_WRITE_TYPE(blob_write_uint32
, uint32_t)
211 BLOB_WRITE_TYPE(blob_write_uint64
, uint64_t)
212 BLOB_WRITE_TYPE(blob_write_intptr
, intptr_t)
214 #define ASSERT_ALIGNED(_offset, _align) \
215 assert(ALIGN((_offset), (_align)) == (_offset))
218 blob_overwrite_uint8 (struct blob
*blob
,
222 ASSERT_ALIGNED(offset
, sizeof(value
));
223 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
227 blob_overwrite_uint32 (struct blob
*blob
,
231 ASSERT_ALIGNED(offset
, sizeof(value
));
232 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
236 blob_overwrite_intptr (struct blob
*blob
,
240 ASSERT_ALIGNED(offset
, sizeof(value
));
241 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
245 blob_write_string(struct blob
*blob
, const char *str
)
247 return blob_write_bytes(blob
, str
, strlen(str
) + 1);
251 blob_reader_init(struct blob_reader
*blob
, const void *data
, size_t size
)
254 blob
->end
= blob
->data
+ size
;
255 blob
->current
= data
;
256 blob
->overrun
= false;
259 /* Check that an object of size \size can be read from this blob.
261 * If not, set blob->overrun to indicate that we attempted to read too far.
264 ensure_can_read(struct blob_reader
*blob
, size_t size
)
269 if (blob
->current
<= blob
->end
&& blob
->end
- blob
->current
>= size
)
272 blob
->overrun
= true;
278 blob_read_bytes(struct blob_reader
*blob
, size_t size
)
282 if (! ensure_can_read (blob
, size
))
287 blob
->current
+= size
;
293 blob_copy_bytes(struct blob_reader
*blob
, void *dest
, size_t size
)
297 bytes
= blob_read_bytes(blob
, size
);
298 if (bytes
== NULL
|| size
== 0)
301 memcpy(dest
, bytes
, size
);
305 blob_skip_bytes(struct blob_reader
*blob
, size_t size
)
307 if (ensure_can_read (blob
, size
))
308 blob
->current
+= size
;
311 /* These next three read functions have identical form. If we add any beyond
312 * these first three we should probably switch to generating these with a
313 * preprocessor macro.
316 #define BLOB_READ_TYPE(name, type) \
318 name(struct blob_reader *blob) \
321 int size = sizeof(ret); \
322 align_blob_reader(blob, size); \
323 if (! ensure_can_read(blob, size)) \
325 ret = *((type*) blob->current); \
326 blob->current += size; \
330 BLOB_READ_TYPE(blob_read_uint8
, uint8_t)
331 BLOB_READ_TYPE(blob_read_uint16
, uint16_t)
332 BLOB_READ_TYPE(blob_read_uint32
, uint32_t)
333 BLOB_READ_TYPE(blob_read_uint64
, uint64_t)
334 BLOB_READ_TYPE(blob_read_intptr
, intptr_t)
337 blob_read_string(struct blob_reader
*blob
)
343 /* If we're already at the end, then this is an overrun. */
344 if (blob
->current
>= blob
->end
) {
345 blob
->overrun
= true;
349 /* Similarly, if there is no zero byte in the data remaining in this blob,
350 * we also consider that an overrun.
352 nul
= memchr(blob
->current
, 0, blob
->end
- blob
->current
);
355 blob
->overrun
= true;
359 size
= nul
- blob
->current
+ 1;
361 assert(ensure_can_read(blob
, size
));
363 ret
= (char *) blob
->current
;
365 blob
->current
+= size
;