--- /dev/null
+// Licensed under BSD-MIT: See LICENSE.
+#ifndef CCAN_PTR_VALID_H
+#define CCAN_PTR_VALID_H
+#include "config.h"
+#include <stdbool.h>
+#include <stdlib.h>
+
+/**
+ * ptr_valid_read - can I safely read from a pointer?
+ * @p: the proposed pointer.
+ *
+ * This function verifies that the pointer @p is safe to dereference for
+ * reading. It is very slow, particularly if the answer is "no".
+ *
+ * Sets errno to EFAULT on failure.
+ *
+ * See Also:
+ * ptr_valid_batch_read()
+ */
+#define ptr_valid_read(p) \
+ ptr_valid_r((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
+
+/**
+ * ptr_valid_write - can I safely write to a pointer?
+ * @p: the proposed pointer.
+ *
+ * This function verifies that the pointer @p is safe to dereference
+ * for writing (and reading). It is very slow, particularly if the
+ * answer is "no".
+ *
+ * Sets errno to EFAULT on failure.
+ *
+ * See Also:
+ * ptr_valid_batch_write()
+ */
+#define ptr_valid_write(p) \
+ ptr_valid_w((p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
+
+/**
+ * ptr_valid_string - can I safely read a string?
+ * @p: the proposed string.
+ *
+ * This function verifies that the pointer @p is safe to dereference
+ * up to a nul character. It is very slow, particularly if the answer
+ * is "no".
+ *
+ * Sets errno to EFAULT on failure.
+ *
+ * See Also:
+ * ptr_valid_batch_string()
+ */
+bool ptr_valid_string(const char *p);
+
+/**
+ * ptr_valid - generic pointer check function
+ * @p: the proposed pointer.
+ * @align: the alignment requirements of the pointer.
+ * @size: the size of the region @p should point to
+ * @write: true if @p should be writable as well as readable.
+ *
+ * This function verifies that the pointer @p is safe to dereference.
+ * It is very slow, particularly if the answer is "no".
+ *
+ * Sets errno to EFAULT on failure.
+ *
+ * See Also:
+ * ptr_valid_batch()
+ */
+bool ptr_valid(const void *p, size_t align, size_t size, bool write);
+
+/**
+ * struct ptr_valid_batch - pointer to store state for batch ptr ops
+ *
+ * Treat as private.
+ */
+struct ptr_valid_batch {
+ unsigned int num_maps;
+ struct ptr_valid_map *maps;
+ int child_pid;
+ int to_child, from_child;
+ void *last;
+ bool last_ok;
+};
+
+/**
+ * ptr_valid_batch_start - prepare for a batch of ptr_valid checks.
+ * @batch: an uninitialized ptr_valid_batch structure.
+ *
+ * This initializes @batch; this same @batch pointer can be reused
+ * until the memory map changes (eg. via mmap(), munmap() or even
+ * malloc() and free()).
+ *
+ * This is useful to check many pointers, because otherwise it can be
+ * extremely slow.
+ *
+ * Example:
+ * struct linked {
+ * struct linked *next;
+ * const char *str;
+ * };
+ *
+ * static bool check_linked_carefully(struct linked *head)
+ * {
+ * struct ptr_valid_batch batch;
+ * struct linked *old = head;
+ * bool half = true;
+ *
+ * // If this fails, we can't check. Assume OK.
+ * if (!ptr_valid_batch_start(&batch))
+ * return true;
+ *
+ * while (head) {
+ * if (!ptr_valid_batch_read(&batch, head))
+ * goto fail;
+ * if (!ptr_valid_batch_string(&batch, head->str))
+ * goto fail;
+ * // Loop detection; move old at half speed of head.
+ * if (half)
+ * old = old->next;
+ * half = !half;
+ * if (head == old) {
+ * errno = ELOOP;
+ * goto fail;
+ * }
+ * }
+ * ptr_valid_batch_end(&batch);
+ * return true;
+ *
+ * fail:
+ * ptr_valid_batch_end(&batch);
+ * return false;
+ * }
+ *
+ * See Also:
+ * ptr_valid_batch_stop()
+ */
+bool ptr_valid_batch_start(struct ptr_valid_batch *batch);
+
+/**
+ * ptr_valid_batch_read - can I safely read from a pointer?
+ * @batch: the batch initialized by ptr_valid_batch_start().
+ * @p: the proposed pointer.
+ *
+ * Batched version of ptr_valid_read().
+ */
+#define ptr_valid_batch_read(batch, p) \
+ ptr_valid_batch_r((batch), \
+ (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
+
+/**
+ * ptr_valid_batch_write - can I safely write to a pointer?
+ * @batch: the batch initialized by ptr_valid_batch_start().
+ * @p: the proposed pointer.
+ *
+ * Batched version of ptr_valid_write().
+ */
+#define ptr_valid_batch_write(batch, p) \
+ ptr_valid_batch_w((batch), \
+ (p), PTR_VALID_ALIGNOF(*(p)), sizeof(*(p)))
+
+/**
+ * ptr_valid_batch_string - can I safely read a string?
+ * @batch: the batch initialized by ptr_valid_batch_start().
+ * @p: the proposed string.
+ *
+ * Batched version of ptr_valid_string().
+ */
+bool ptr_valid_batch_string(struct ptr_valid_batch *batch, const char *p);
+
+/**
+ * ptr_valid_batch - generic batched pointer check function
+ * @batch: the batch initialized by ptr_valid_batch_start().
+ * @p: the proposed pointer.
+ * @align: the alignment requirements of the pointer.
+ * @size: the size of the region @p should point to
+ * @write: true if @p should be writable as well as readable.
+ *
+ * Batched version of ptr_valid().
+ */
+bool ptr_valid_batch(struct ptr_valid_batch *batch,
+ const void *p, size_t alignment, size_t size, bool write);
+
+/**
+ * ptr_valid_batch_end - end a batch of ptr_valid checks.
+ * @batch: a ptr_valid_batch structure.
+ *
+ * This is used after all checks are complete.
+ *
+ * See Also:
+ * ptr_valid_batch_start()
+ */
+void ptr_valid_batch_end(struct ptr_valid_batch *batch);
+
+
+/* These wrappers get constness correct. */
+static inline bool ptr_valid_r(const void *p, size_t align, size_t size)
+{
+ return ptr_valid(p, align, size, false);
+}
+
+static inline bool ptr_valid_w(void *p, size_t align, size_t size)
+{
+ return ptr_valid(p, align, size, true);
+}
+
+static inline bool ptr_valid_batch_r(struct ptr_valid_batch *batch,
+ const void *p, size_t align, size_t size)
+{
+ return ptr_valid_batch(batch, p, align, size, false);
+}
+
+static inline bool ptr_valid_batch_w(struct ptr_valid_batch *batch,
+ void *p, size_t align, size_t size)
+{
+ return ptr_valid_batch(batch, p, align, size, true);
+}
+
+struct ptr_valid_map {
+ const char *start, *end;
+ bool is_write;
+};
+
+#if HAVE_ALIGNOF
+#define PTR_VALID_ALIGNOF(var) __alignof__(var)
+#else
+/* Can't check this... */
+#define PTR_VALID_ALIGNOF(var) 1
+#endif
+#endif /* CCAN_PTR_VALID_H */