1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include <string.h> 25b8e80941Smrg 26b8e80941Smrg#include "main/macros.h" 27b8e80941Smrg#include "blob.h" 28b8e80941Smrg 29b8e80941Smrg#ifdef HAVE_VALGRIND 30b8e80941Smrg#include <valgrind.h> 31b8e80941Smrg#include <memcheck.h> 32b8e80941Smrg#define VG(x) x 33b8e80941Smrg#else 34b8e80941Smrg#define VG(x) 35b8e80941Smrg#endif 36b8e80941Smrg 37b8e80941Smrg#define BLOB_INITIAL_SIZE 4096 38b8e80941Smrg 39b8e80941Smrg/* Ensure that \blob will be able to fit an additional object of size 40b8e80941Smrg * \additional. The growing (if any) will occur by doubling the existing 41b8e80941Smrg * allocation. 42b8e80941Smrg */ 43b8e80941Smrgstatic bool 44b8e80941Smrggrow_to_fit(struct blob *blob, size_t additional) 45b8e80941Smrg{ 46b8e80941Smrg size_t to_allocate; 47b8e80941Smrg uint8_t *new_data; 48b8e80941Smrg 49b8e80941Smrg if (blob->out_of_memory) 50b8e80941Smrg return false; 51b8e80941Smrg 52b8e80941Smrg if (blob->size + additional <= blob->allocated) 53b8e80941Smrg return true; 54b8e80941Smrg 55b8e80941Smrg if (blob->fixed_allocation) { 56b8e80941Smrg blob->out_of_memory = true; 57b8e80941Smrg return false; 58b8e80941Smrg } 59b8e80941Smrg 60b8e80941Smrg if (blob->allocated == 0) 61b8e80941Smrg to_allocate = BLOB_INITIAL_SIZE; 62b8e80941Smrg else 63b8e80941Smrg to_allocate = blob->allocated * 2; 64b8e80941Smrg 65b8e80941Smrg to_allocate = MAX2(to_allocate, blob->allocated + additional); 66b8e80941Smrg 67b8e80941Smrg new_data = realloc(blob->data, to_allocate); 68b8e80941Smrg if (new_data == NULL) { 69b8e80941Smrg blob->out_of_memory = true; 70b8e80941Smrg return false; 71b8e80941Smrg } 72b8e80941Smrg 73b8e80941Smrg blob->data = new_data; 74b8e80941Smrg blob->allocated = to_allocate; 75b8e80941Smrg 76b8e80941Smrg return true; 77b8e80941Smrg} 78b8e80941Smrg 79b8e80941Smrg/* Align the blob->size so that reading or writing a value at (blob->data + 80b8e80941Smrg * blob->size) will result in an access aligned to a granularity of \alignment 81b8e80941Smrg * bytes. 82b8e80941Smrg * 83b8e80941Smrg * \return True unless allocation fails 84b8e80941Smrg */ 85b8e80941Smrgstatic bool 86b8e80941Smrgalign_blob(struct blob *blob, size_t alignment) 87b8e80941Smrg{ 88b8e80941Smrg const size_t new_size = ALIGN(blob->size, alignment); 89b8e80941Smrg 90b8e80941Smrg if (blob->size < new_size) { 91b8e80941Smrg if (!grow_to_fit(blob, new_size - blob->size)) 92b8e80941Smrg return false; 93b8e80941Smrg 94b8e80941Smrg if (blob->data) 95b8e80941Smrg memset(blob->data + blob->size, 0, new_size - blob->size); 96b8e80941Smrg blob->size = new_size; 97b8e80941Smrg } 98b8e80941Smrg 99b8e80941Smrg return true; 100b8e80941Smrg} 101b8e80941Smrg 102b8e80941Smrgstatic void 103b8e80941Smrgalign_blob_reader(struct blob_reader *blob, size_t alignment) 104b8e80941Smrg{ 105b8e80941Smrg blob->current = blob->data + ALIGN(blob->current - blob->data, alignment); 106b8e80941Smrg} 107b8e80941Smrg 108b8e80941Smrgvoid 109b8e80941Smrgblob_init(struct blob *blob) 110b8e80941Smrg{ 111b8e80941Smrg blob->data = NULL; 112b8e80941Smrg blob->allocated = 0; 113b8e80941Smrg blob->size = 0; 114b8e80941Smrg blob->fixed_allocation = false; 115b8e80941Smrg blob->out_of_memory = false; 116b8e80941Smrg} 117b8e80941Smrg 118b8e80941Smrgvoid 119b8e80941Smrgblob_init_fixed(struct blob *blob, void *data, size_t size) 120b8e80941Smrg{ 121b8e80941Smrg blob->data = data; 122b8e80941Smrg blob->allocated = size; 123b8e80941Smrg blob->size = 0; 124b8e80941Smrg blob->fixed_allocation = true; 125b8e80941Smrg blob->out_of_memory = false; 126b8e80941Smrg} 127b8e80941Smrg 128b8e80941Smrgbool 129b8e80941Smrgblob_overwrite_bytes(struct blob *blob, 130b8e80941Smrg size_t offset, 131b8e80941Smrg const void *bytes, 132b8e80941Smrg size_t to_write) 133b8e80941Smrg{ 134b8e80941Smrg /* Detect an attempt to overwrite data out of bounds. */ 135b8e80941Smrg if (offset + to_write < offset || blob->size < offset + to_write) 136b8e80941Smrg return false; 137b8e80941Smrg 138b8e80941Smrg VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write)); 139b8e80941Smrg 140b8e80941Smrg if (blob->data) 141b8e80941Smrg memcpy(blob->data + offset, bytes, to_write); 142b8e80941Smrg 143b8e80941Smrg return true; 144b8e80941Smrg} 145b8e80941Smrg 146b8e80941Smrgbool 147b8e80941Smrgblob_write_bytes(struct blob *blob, const void *bytes, size_t to_write) 148b8e80941Smrg{ 149b8e80941Smrg if (! grow_to_fit(blob, to_write)) 150b8e80941Smrg return false; 151b8e80941Smrg 152b8e80941Smrg VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write)); 153b8e80941Smrg 154b8e80941Smrg if (blob->data) 155b8e80941Smrg memcpy(blob->data + blob->size, bytes, to_write); 156b8e80941Smrg blob->size += to_write; 157b8e80941Smrg 158b8e80941Smrg return true; 159b8e80941Smrg} 160b8e80941Smrg 161b8e80941Smrgintptr_t 162b8e80941Smrgblob_reserve_bytes(struct blob *blob, size_t to_write) 163b8e80941Smrg{ 164b8e80941Smrg intptr_t ret; 165b8e80941Smrg 166b8e80941Smrg if (! grow_to_fit (blob, to_write)) 167b8e80941Smrg return -1; 168b8e80941Smrg 169b8e80941Smrg ret = blob->size; 170b8e80941Smrg blob->size += to_write; 171b8e80941Smrg 172b8e80941Smrg return ret; 173b8e80941Smrg} 174b8e80941Smrg 175b8e80941Smrgintptr_t 176b8e80941Smrgblob_reserve_uint32(struct blob *blob) 177b8e80941Smrg{ 178b8e80941Smrg align_blob(blob, sizeof(uint32_t)); 179b8e80941Smrg return blob_reserve_bytes(blob, sizeof(uint32_t)); 180b8e80941Smrg} 181b8e80941Smrg 182b8e80941Smrgintptr_t 183b8e80941Smrgblob_reserve_intptr(struct blob *blob) 184b8e80941Smrg{ 185b8e80941Smrg align_blob(blob, sizeof(intptr_t)); 186b8e80941Smrg return blob_reserve_bytes(blob, sizeof(intptr_t)); 187b8e80941Smrg} 188b8e80941Smrg 189b8e80941Smrgbool 190b8e80941Smrgblob_write_uint32(struct blob *blob, uint32_t value) 191b8e80941Smrg{ 192b8e80941Smrg align_blob(blob, sizeof(value)); 193b8e80941Smrg 194b8e80941Smrg return blob_write_bytes(blob, &value, sizeof(value)); 195b8e80941Smrg} 196b8e80941Smrg 197b8e80941Smrg#define ASSERT_ALIGNED(_offset, _align) \ 198b8e80941Smrg assert(ALIGN((_offset), (_align)) == (_offset)) 199b8e80941Smrg 200b8e80941Smrgbool 201b8e80941Smrgblob_overwrite_uint32 (struct blob *blob, 202b8e80941Smrg size_t offset, 203b8e80941Smrg uint32_t value) 204b8e80941Smrg{ 205b8e80941Smrg ASSERT_ALIGNED(offset, sizeof(value)); 206b8e80941Smrg return blob_overwrite_bytes(blob, offset, &value, sizeof(value)); 207b8e80941Smrg} 208b8e80941Smrg 209b8e80941Smrgbool 210b8e80941Smrgblob_write_uint64(struct blob *blob, uint64_t value) 211b8e80941Smrg{ 212b8e80941Smrg align_blob(blob, sizeof(value)); 213b8e80941Smrg 214b8e80941Smrg return blob_write_bytes(blob, &value, sizeof(value)); 215b8e80941Smrg} 216b8e80941Smrg 217b8e80941Smrgbool 218b8e80941Smrgblob_write_intptr(struct blob *blob, intptr_t value) 219b8e80941Smrg{ 220b8e80941Smrg align_blob(blob, sizeof(value)); 221b8e80941Smrg 222b8e80941Smrg return blob_write_bytes(blob, &value, sizeof(value)); 223b8e80941Smrg} 224b8e80941Smrg 225b8e80941Smrgbool 226b8e80941Smrgblob_overwrite_intptr (struct blob *blob, 227b8e80941Smrg size_t offset, 228b8e80941Smrg intptr_t value) 229b8e80941Smrg{ 230b8e80941Smrg ASSERT_ALIGNED(offset, sizeof(value)); 231b8e80941Smrg return blob_overwrite_bytes(blob, offset, &value, sizeof(value)); 232b8e80941Smrg} 233b8e80941Smrg 234b8e80941Smrgbool 235b8e80941Smrgblob_write_string(struct blob *blob, const char *str) 236b8e80941Smrg{ 237b8e80941Smrg return blob_write_bytes(blob, str, strlen(str) + 1); 238b8e80941Smrg} 239b8e80941Smrg 240b8e80941Smrgvoid 241b8e80941Smrgblob_reader_init(struct blob_reader *blob, const void *data, size_t size) 242b8e80941Smrg{ 243b8e80941Smrg blob->data = data; 244b8e80941Smrg blob->end = blob->data + size; 245b8e80941Smrg blob->current = data; 246b8e80941Smrg blob->overrun = false; 247b8e80941Smrg} 248b8e80941Smrg 249b8e80941Smrg/* Check that an object of size \size can be read from this blob. 250b8e80941Smrg * 251b8e80941Smrg * If not, set blob->overrun to indicate that we attempted to read too far. 252b8e80941Smrg */ 253b8e80941Smrgstatic bool 254b8e80941Smrgensure_can_read(struct blob_reader *blob, size_t size) 255b8e80941Smrg{ 256b8e80941Smrg if (blob->overrun) 257b8e80941Smrg return false; 258b8e80941Smrg 259b8e80941Smrg if (blob->current <= blob->end && blob->end - blob->current >= size) 260b8e80941Smrg return true; 261b8e80941Smrg 262b8e80941Smrg blob->overrun = true; 263b8e80941Smrg 264b8e80941Smrg return false; 265b8e80941Smrg} 266b8e80941Smrg 267b8e80941Smrgconst void * 268b8e80941Smrgblob_read_bytes(struct blob_reader *blob, size_t size) 269b8e80941Smrg{ 270b8e80941Smrg const void *ret; 271b8e80941Smrg 272b8e80941Smrg if (! ensure_can_read (blob, size)) 273b8e80941Smrg return NULL; 274b8e80941Smrg 275b8e80941Smrg ret = blob->current; 276b8e80941Smrg 277b8e80941Smrg blob->current += size; 278b8e80941Smrg 279b8e80941Smrg return ret; 280b8e80941Smrg} 281b8e80941Smrg 282b8e80941Smrgvoid 283b8e80941Smrgblob_copy_bytes(struct blob_reader *blob, void *dest, size_t size) 284b8e80941Smrg{ 285b8e80941Smrg const void *bytes; 286b8e80941Smrg 287b8e80941Smrg bytes = blob_read_bytes(blob, size); 288b8e80941Smrg if (bytes == NULL) 289b8e80941Smrg return; 290b8e80941Smrg 291b8e80941Smrg memcpy(dest, bytes, size); 292b8e80941Smrg} 293b8e80941Smrg 294b8e80941Smrgvoid 295b8e80941Smrgblob_skip_bytes(struct blob_reader *blob, size_t size) 296b8e80941Smrg{ 297b8e80941Smrg if (ensure_can_read (blob, size)) 298b8e80941Smrg blob->current += size; 299b8e80941Smrg} 300b8e80941Smrg 301b8e80941Smrg/* These next three read functions have identical form. If we add any beyond 302b8e80941Smrg * these first three we should probably switch to generating these with a 303b8e80941Smrg * preprocessor macro. 304b8e80941Smrg*/ 305b8e80941Smrguint32_t 306b8e80941Smrgblob_read_uint32(struct blob_reader *blob) 307b8e80941Smrg{ 308b8e80941Smrg uint32_t ret; 309b8e80941Smrg int size = sizeof(ret); 310b8e80941Smrg 311b8e80941Smrg align_blob_reader(blob, size); 312b8e80941Smrg 313b8e80941Smrg if (! ensure_can_read(blob, size)) 314b8e80941Smrg return 0; 315b8e80941Smrg 316b8e80941Smrg ret = *((uint32_t*) blob->current); 317b8e80941Smrg 318b8e80941Smrg blob->current += size; 319b8e80941Smrg 320b8e80941Smrg return ret; 321b8e80941Smrg} 322b8e80941Smrg 323b8e80941Smrguint64_t 324b8e80941Smrgblob_read_uint64(struct blob_reader *blob) 325b8e80941Smrg{ 326b8e80941Smrg uint64_t ret; 327b8e80941Smrg int size = sizeof(ret); 328b8e80941Smrg 329b8e80941Smrg align_blob_reader(blob, size); 330b8e80941Smrg 331b8e80941Smrg if (! ensure_can_read(blob, size)) 332b8e80941Smrg return 0; 333b8e80941Smrg 334b8e80941Smrg ret = *((uint64_t*) blob->current); 335b8e80941Smrg 336b8e80941Smrg blob->current += size; 337b8e80941Smrg 338b8e80941Smrg return ret; 339b8e80941Smrg} 340b8e80941Smrg 341b8e80941Smrgintptr_t 342b8e80941Smrgblob_read_intptr(struct blob_reader *blob) 343b8e80941Smrg{ 344b8e80941Smrg intptr_t ret; 345b8e80941Smrg int size = sizeof(ret); 346b8e80941Smrg 347b8e80941Smrg align_blob_reader(blob, size); 348b8e80941Smrg 349b8e80941Smrg if (! ensure_can_read(blob, size)) 350b8e80941Smrg return 0; 351b8e80941Smrg 352b8e80941Smrg ret = *((intptr_t *) blob->current); 353b8e80941Smrg 354b8e80941Smrg blob->current += size; 355b8e80941Smrg 356b8e80941Smrg return ret; 357b8e80941Smrg} 358b8e80941Smrg 359b8e80941Smrgchar * 360b8e80941Smrgblob_read_string(struct blob_reader *blob) 361b8e80941Smrg{ 362b8e80941Smrg int size; 363b8e80941Smrg char *ret; 364b8e80941Smrg uint8_t *nul; 365b8e80941Smrg 366b8e80941Smrg /* If we're already at the end, then this is an overrun. */ 367b8e80941Smrg if (blob->current >= blob->end) { 368b8e80941Smrg blob->overrun = true; 369b8e80941Smrg return NULL; 370b8e80941Smrg } 371b8e80941Smrg 372b8e80941Smrg /* Similarly, if there is no zero byte in the data remaining in this blob, 373b8e80941Smrg * we also consider that an overrun. 374b8e80941Smrg */ 375b8e80941Smrg nul = memchr(blob->current, 0, blob->end - blob->current); 376b8e80941Smrg 377b8e80941Smrg if (nul == NULL) { 378b8e80941Smrg blob->overrun = true; 379b8e80941Smrg return NULL; 380b8e80941Smrg } 381b8e80941Smrg 382b8e80941Smrg size = nul - blob->current + 1; 383b8e80941Smrg 384b8e80941Smrg assert(ensure_can_read(blob, size)); 385b8e80941Smrg 386b8e80941Smrg ret = (char *) blob->current; 387b8e80941Smrg 388b8e80941Smrg blob->current += size; 389b8e80941Smrg 390b8e80941Smrg return ret; 391b8e80941Smrg} 392