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
->size
+ additional
<= blob
->allocated
)
52 if (blob
->allocated
== 0)
53 to_allocate
= BLOB_INITIAL_SIZE
;
55 to_allocate
= blob
->allocated
* 2;
57 to_allocate
= MAX2(to_allocate
, blob
->allocated
+ additional
);
59 new_data
= realloc(blob
->data
, to_allocate
);
63 blob
->data
= new_data
;
64 blob
->allocated
= to_allocate
;
69 /* Align the blob->size so that reading or writing a value at (blob->data +
70 * blob->size) will result in an access aligned to a granularity of \alignment
73 * \return True unless allocation fails
76 align_blob(struct blob
*blob
, size_t alignment
)
78 const size_t new_size
= ALIGN(blob
->size
, alignment
);
80 if (blob
->size
< new_size
) {
81 if (!grow_to_fit(blob
, new_size
- blob
->size
))
84 memset(blob
->data
+ blob
->size
, 0, new_size
- blob
->size
);
85 blob
->size
= new_size
;
92 align_blob_reader(struct blob_reader
*blob
, size_t alignment
)
94 blob
->current
= blob
->data
+ ALIGN(blob
->current
- blob
->data
, alignment
);
100 struct blob
*blob
= (struct blob
*) malloc(sizeof(struct blob
));
112 blob_overwrite_bytes(struct blob
*blob
,
117 /* Detect an attempt to overwrite data out of bounds. */
118 if (blob
->size
< offset
+ to_write
)
121 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
123 memcpy(blob
->data
+ offset
, bytes
, to_write
);
129 blob_write_bytes(struct blob
*blob
, const void *bytes
, size_t to_write
)
131 if (! grow_to_fit(blob
, to_write
))
134 VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes
, to_write
));
136 memcpy(blob
->data
+ blob
->size
, bytes
, to_write
);
137 blob
->size
+= to_write
;
143 blob_reserve_bytes(struct blob
*blob
, size_t to_write
)
147 if (! grow_to_fit (blob
, to_write
))
150 ret
= blob
->data
+ blob
->size
;
151 blob
->size
+= to_write
;
157 blob_write_uint32(struct blob
*blob
, uint32_t value
)
159 align_blob(blob
, sizeof(value
));
161 return blob_write_bytes(blob
, &value
, sizeof(value
));
165 blob_overwrite_uint32 (struct blob
*blob
,
169 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
173 blob_write_uint64(struct blob
*blob
, uint64_t value
)
175 align_blob(blob
, sizeof(value
));
177 return blob_write_bytes(blob
, &value
, sizeof(value
));
181 blob_write_intptr(struct blob
*blob
, intptr_t value
)
183 align_blob(blob
, sizeof(value
));
185 return blob_write_bytes(blob
, &value
, sizeof(value
));
189 blob_write_string(struct blob
*blob
, const char *str
)
191 return blob_write_bytes(blob
, str
, strlen(str
) + 1);
195 blob_reader_init(struct blob_reader
*blob
, uint8_t *data
, size_t size
)
198 blob
->end
= data
+ size
;
199 blob
->current
= data
;
200 blob
->overrun
= false;
203 /* Check that an object of size \size can be read from this blob.
205 * If not, set blob->overrun to indicate that we attempted to read too far.
208 ensure_can_read(struct blob_reader
*blob
, size_t size
)
210 if (blob
->current
< blob
->end
&& blob
->end
- blob
->current
>= size
)
213 blob
->overrun
= true;
219 blob_read_bytes(struct blob_reader
*blob
, size_t size
)
223 if (! ensure_can_read (blob
, size
))
228 blob
->current
+= size
;
234 blob_copy_bytes(struct blob_reader
*blob
, uint8_t *dest
, size_t size
)
238 bytes
= blob_read_bytes(blob
, size
);
242 memcpy(dest
, bytes
, size
);
245 /* These next three read functions have identical form. If we add any beyond
246 * these first three we should probably switch to generating these with a
247 * preprocessor macro.
250 blob_read_uint32(struct blob_reader
*blob
)
253 int size
= sizeof(ret
);
255 align_blob_reader(blob
, size
);
257 if (! ensure_can_read(blob
, size
))
260 ret
= *((uint32_t*) blob
->current
);
262 blob
->current
+= size
;
268 blob_read_uint64(struct blob_reader
*blob
)
271 int size
= sizeof(ret
);
273 align_blob_reader(blob
, size
);
275 if (! ensure_can_read(blob
, size
))
278 ret
= *((uint64_t*) blob
->current
);
280 blob
->current
+= size
;
286 blob_read_intptr(struct blob_reader
*blob
)
289 int size
= sizeof(ret
);
291 align_blob_reader(blob
, size
);
293 if (! ensure_can_read(blob
, size
))
296 ret
= *((intptr_t *) blob
->current
);
298 blob
->current
+= size
;
304 blob_read_string(struct blob_reader
*blob
)
310 /* If we're already at the end, then this is an overrun. */
311 if (blob
->current
>= blob
->end
) {
312 blob
->overrun
= true;
316 /* Similarly, if there is no zero byte in the data remaining in this blob,
317 * we also consider that an overrun.
319 nul
= memchr(blob
->current
, 0, blob
->end
- blob
->current
);
322 blob
->overrun
= true;
326 size
= nul
- blob
->current
+ 1;
328 assert(ensure_can_read(blob
, size
));
330 ret
= (char *) blob
->current
;
332 blob
->current
+= size
;