if (!grow_to_fit(blob, new_size - blob->size))
return false;
- memset(blob->data + blob->size, 0, new_size - blob->size);
+ if (blob->data)
+ memset(blob->data + blob->size, 0, new_size - blob->size);
blob->size = new_size;
}
size_t to_write)
{
/* Detect an attempt to overwrite data out of bounds. */
- if (blob->size < offset + to_write)
+ if (offset + to_write < offset || blob->size < offset + to_write)
return false;
VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write));
- memcpy(blob->data + offset, bytes, to_write);
+ if (blob->data)
+ memcpy(blob->data + offset, bytes, to_write);
return true;
}
VG(VALGRIND_CHECK_MEM_IS_DEFINED(bytes, to_write));
- memcpy(blob->data + blob->size, bytes, to_write);
+ if (blob->data)
+ memcpy(blob->data + blob->size, bytes, to_write);
blob->size += to_write;
return true;
}
-uint8_t *
+intptr_t
blob_reserve_bytes(struct blob *blob, size_t to_write)
{
- uint8_t *ret;
+ intptr_t ret;
if (! grow_to_fit (blob, to_write))
- return NULL;
+ return -1;
- ret = blob->data + blob->size;
+ ret = blob->size;
blob->size += to_write;
return ret;
}
+intptr_t
+blob_reserve_uint32(struct blob *blob)
+{
+ align_blob(blob, sizeof(uint32_t));
+ return blob_reserve_bytes(blob, sizeof(uint32_t));
+}
+
+intptr_t
+blob_reserve_intptr(struct blob *blob)
+{
+ align_blob(blob, sizeof(intptr_t));
+ return blob_reserve_bytes(blob, sizeof(intptr_t));
+}
+
bool
blob_write_uint32(struct blob *blob, uint32_t value)
{
return blob_write_bytes(blob, &value, sizeof(value));
}
+#define ASSERT_ALIGNED(_offset, _align) \
+ assert(ALIGN((_offset), (_align)) == (_offset))
+
bool
blob_overwrite_uint32 (struct blob *blob,
size_t offset,
uint32_t value)
{
+ ASSERT_ALIGNED(offset, sizeof(value));
return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
}
return blob_write_bytes(blob, &value, sizeof(value));
}
+bool
+blob_overwrite_intptr (struct blob *blob,
+ size_t offset,
+ intptr_t value)
+{
+ ASSERT_ALIGNED(offset, sizeof(value));
+ return blob_overwrite_bytes(blob, offset, &value, sizeof(value));
+}
+
bool
blob_write_string(struct blob *blob, const char *str)
{
}
void
-blob_reader_init(struct blob_reader *blob, uint8_t *data, size_t size)
+blob_reader_init(struct blob_reader *blob, const void *data, size_t size)
{
blob->data = data;
- blob->end = data + size;
+ blob->end = blob->data + size;
blob->current = data;
blob->overrun = false;
}
if (blob->overrun)
return false;
- if (blob->current < blob->end && blob->end - blob->current >= size)
+ if (blob->current <= blob->end && blob->end - blob->current >= size)
return true;
blob->overrun = true;
return false;
}
-void *
+const void *
blob_read_bytes(struct blob_reader *blob, size_t size)
{
- void *ret;
+ const void *ret;
if (! ensure_can_read (blob, size))
return NULL;
}
void
-blob_copy_bytes(struct blob_reader *blob, uint8_t *dest, size_t size)
+blob_copy_bytes(struct blob_reader *blob, void *dest, size_t size)
{
- uint8_t *bytes;
+ const void *bytes;
bytes = blob_read_bytes(blob, size);
if (bytes == NULL)
memcpy(dest, bytes, size);
}
+void
+blob_skip_bytes(struct blob_reader *blob, size_t size)
+{
+ if (ensure_can_read (blob, size))
+ blob->current += size;
+}
+
/* These next three read functions have identical form. If we add any beyond
* these first three we should probably switch to generating these with a
* preprocessor macro.