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"
27 #include "util/ralloc.h"
30 #define BLOB_INITIAL_SIZE 4096
32 /* Ensure that \blob will be able to fit an additional object of size
33 * \additional. The growing (if any) will occur by doubling the existing
37 grow_to_fit(struct blob
*blob
, size_t additional
)
42 if (blob
->size
+ additional
<= blob
->allocated
)
45 if (blob
->allocated
== 0)
46 to_allocate
= BLOB_INITIAL_SIZE
;
48 to_allocate
= blob
->allocated
* 2;
50 to_allocate
= MAX2(to_allocate
, blob
->allocated
+ additional
);
52 new_data
= reralloc_size(blob
, blob
->data
, to_allocate
);
56 blob
->data
= new_data
;
57 blob
->allocated
= to_allocate
;
62 /* Align the blob->size so that reading or writing a value at (blob->data +
63 * blob->size) will result in an access aligned to a granularity of \alignment
66 * \return True unless allocation fails
69 align_blob(struct blob
*blob
, size_t alignment
)
71 const size_t new_size
= ALIGN(blob
->size
, alignment
);
73 if (! grow_to_fit (blob
, new_size
- blob
->size
))
76 blob
->size
= new_size
;
82 align_blob_reader(struct blob_reader
*blob
, size_t alignment
)
84 blob
->current
= blob
->data
+ ALIGN(blob
->current
- blob
->data
, alignment
);
88 blob_create(void *mem_ctx
)
92 blob
= ralloc(mem_ctx
, struct blob
);
104 blob_overwrite_bytes(struct blob
*blob
,
109 /* Detect an attempt to overwrite data out of bounds. */
110 if (offset
< 0 || blob
->size
- offset
< to_write
)
113 memcpy(blob
->data
+ offset
, bytes
, to_write
);
119 blob_write_bytes(struct blob
*blob
, const void *bytes
, size_t to_write
)
121 if (! grow_to_fit(blob
, to_write
))
124 memcpy(blob
->data
+ blob
->size
, bytes
, to_write
);
125 blob
->size
+= to_write
;
131 blob_reserve_bytes(struct blob
*blob
, size_t to_write
)
135 if (! grow_to_fit (blob
, to_write
))
138 ret
= blob
->data
+ blob
->size
;
139 blob
->size
+= to_write
;
145 blob_write_uint32(struct blob
*blob
, uint32_t value
)
147 align_blob(blob
, sizeof(value
));
149 return blob_write_bytes(blob
, &value
, sizeof(value
));
153 blob_overwrite_uint32 (struct blob
*blob
,
157 return blob_overwrite_bytes(blob
, offset
, &value
, sizeof(value
));
161 blob_write_uint64(struct blob
*blob
, uint64_t value
)
163 align_blob(blob
, sizeof(value
));
165 return blob_write_bytes(blob
, &value
, sizeof(value
));
169 blob_write_intptr(struct blob
*blob
, intptr_t value
)
171 align_blob(blob
, sizeof(value
));
173 return blob_write_bytes(blob
, &value
, sizeof(value
));
177 blob_write_string(struct blob
*blob
, const char *str
)
179 return blob_write_bytes(blob
, str
, strlen(str
) + 1);
183 blob_reader_init(struct blob_reader
*blob
, uint8_t *data
, size_t size
)
186 blob
->end
= data
+ size
;
187 blob
->current
= data
;
188 blob
->overrun
= false;
191 /* Check that an object of size \size can be read from this blob.
193 * If not, set blob->overrun to indicate that we attempted to read too far.
196 ensure_can_read(struct blob_reader
*blob
, size_t size
)
198 if (blob
->current
< blob
->end
&& blob
->end
- blob
->current
>= size
)
201 blob
->overrun
= true;
207 blob_read_bytes(struct blob_reader
*blob
, size_t size
)
211 if (! ensure_can_read (blob
, size
))
216 blob
->current
+= size
;
222 blob_copy_bytes(struct blob_reader
*blob
, uint8_t *dest
, size_t size
)
226 bytes
= blob_read_bytes(blob
, size
);
230 memcpy(dest
, bytes
, size
);
233 /* These next three read functions have identical form. If we add any beyond
234 * these first three we should probably switch to generating these with a
235 * preprocessor macro.
238 blob_read_uint32(struct blob_reader
*blob
)
241 int size
= sizeof(ret
);
243 align_blob_reader(blob
, size
);
245 if (! ensure_can_read(blob
, size
))
248 ret
= *((uint32_t*) blob
->current
);
250 blob
->current
+= size
;
256 blob_read_uint64(struct blob_reader
*blob
)
259 int size
= sizeof(ret
);
261 align_blob_reader(blob
, size
);
263 if (! ensure_can_read(blob
, size
))
266 ret
= *((uint64_t*) blob
->current
);
268 blob
->current
+= size
;
274 blob_read_intptr(struct blob_reader
*blob
)
277 int size
= sizeof(ret
);
279 align_blob_reader(blob
, size
);
281 if (! ensure_can_read(blob
, size
))
284 ret
= *((intptr_t *) blob
->current
);
286 blob
->current
+= size
;
292 blob_read_string(struct blob_reader
*blob
)
298 /* If we're already at the end, then this is an overrun. */
299 if (blob
->current
>= blob
->end
) {
300 blob
->overrun
= true;
304 /* Similarly, if there is no zero byte in the data remaining in this blob,
305 * we also consider that an overrun.
307 nul
= memchr(blob
->current
, 0, blob
->end
- blob
->current
);
310 blob
->overrun
= true;
314 size
= nul
- blob
->current
+ 1;
316 assert(ensure_can_read(blob
, size
));
318 ret
= (char *) blob
->current
;
320 blob
->current
+= size
;