40#define BUF_SIZE_MAX 1000000
51#ifdef VERIFY_ALIGNMENT
52#define BUF_INIT_TRACKING
80#ifdef BUF_INIT_TRACKING
139#define BPTR(buf) (buf_bptr(buf))
141#define BEND(buf) (buf_bend(buf))
143#define BLAST(buf) (buf_blast(buf))
145#define BLEN(buf) (buf_len(buf))
147#define BLENZ(buf) ((size_t)buf_len(buf))
149#define BDEF(buf) (buf_defined(buf))
151#define BSTR(buf) (buf_str(buf))
153#define BCAP(buf) (buf_forward_capacity(buf))
218size_t array_mult_safe(
const size_t m1,
const size_t m2,
const size_t extra);
221#define PA_BRACKET (1 << 0)
350#ifdef BUF_INIT_TRACKING
351#define buf_init(buf, offset) buf_init_debug(buf, offset, __FILE__, __LINE__)
353bool buf_init_debug(
struct buffer *buf,
int offset,
const char *file,
int line);
356#define buf_init(buf, offset) buf_init_dowork(buf, offset)
371 freeaddrinfo((
struct addrinfo *)addr);
375static inline struct buffer
378 return (
struct buffer){ 0 };
392 return buf->
data != NULL;
417static inline uint8_t *
457static inline uint8_t *
471static inline uint8_t *
573 if (offset < 0 || offset > buf->
capacity || buf->
data == NULL)
604 if (size > 0 && data)
631 buf->
data = (uint8_t *)data;
650 strncpy(dest, src, maxlen - 1);
651 dest[maxlen - 1] = 0;
708 SecureZeroMemory(data, len);
709#elif defined(__GNUC__) || defined(__clang__)
710 memset(data, 0, len);
711 __asm__ __volatile__(
"" : :
"r"(data) :
"memory");
713 volatile char *p = (
volatile char *)data;
738#if __USE_MINGW_ANSI_STDIO
798void chomp(
char *str);
875bool buf_parse(
struct buffer *buf,
const int delim,
char *line,
const int size);
884#define FHE_SPACE_BREAK_MASK 0xFF
886#define FHE_CAPS 0x100
903char *
format_hex_ex(
const uint8_t *data,
size_t size,
size_t maxoutput,
unsigned int space_break_flags,
1560 if (size !=
src->len)
1629const char *
np(
const char *
str);
1636#define CC_ANY (1 << 0)
1637#define CC_NULL (1 << 1)
1639#define CC_ALNUM (1 << 2)
1640#define CC_ALPHA (1 << 3)
1641#define CC_ASCII (1 << 4)
1642#define CC_CNTRL (1 << 5)
1643#define CC_DIGIT (1 << 6)
1644#define CC_PRINT (1 << 7)
1645#define CC_PUNCT (1 << 8)
1646#define CC_SPACE (1 << 9)
1647#define CC_XDIGIT (1 << 10)
1649#define CC_BLANK (1 << 11)
1650#define CC_NEWLINE (1 << 12)
1651#define CC_CR (1 << 13)
1653#define CC_BACKSLASH (1 << 14)
1654#define CC_UNDERBAR (1 << 15)
1655#define CC_DASH (1 << 16)
1656#define CC_DOT (1 << 17)
1657#define CC_COMMA (1 << 18)
1658#define CC_COLON (1 << 19)
1659#define CC_SLASH (1 << 20)
1660#define CC_SINGLE_QUOTE (1 << 21)
1661#define CC_DOUBLE_QUOTE (1 << 22)
1662#define CC_REVERSE_QUOTE (1 << 23)
1663#define CC_AT (1 << 24)
1664#define CC_EQUAL (1 << 25)
1665#define CC_LESS_THAN (1 << 26)
1666#define CC_GREATER_THAN (1 << 27)
1667#define CC_PIPE (1 << 28)
1668#define CC_QUESTION_MARK (1 << 29)
1669#define CC_ASTERISK (1 << 30)
1672#define CC_NAME (CC_ALNUM | CC_UNDERBAR)
1673#define CC_CRLF (CC_CR | CC_NEWLINE)
1683bool char_class(
const unsigned char c,
const unsigned int flags);
1788#if __USE_MINGW_ANSI_STDIO
1799#ifdef VERIFY_ALIGNMENT
1812#define verify_align_4(ptr) valign4(buf, __FILE__, __LINE__)
1814#define verify_align_4(ptr)
1861 return a->list !=
NULL;
1873 a->list_special =
NULL;
1944#if UINTPTR_MAX <= UINT32_MAX
1949#define ALLOC_SIZE_MAX (1u << 30)
1952#define ALLOC_SIZE_MAX ((size_t)1 << 32)
1963#define ALLOC_OBJ(dptr, type) \
1965 check_malloc_return((dptr) = (type *)malloc(sizeof(type))); \
1974#define ALLOC_OBJ_CLEAR(dptr, type) \
1976 ALLOC_OBJ(dptr, type); \
1977 memset((dptr), 0, sizeof(type)); \
1990#define ALLOC_ARRAY(dptr, type, n) \
1992 check_malloc_return((dptr) = (type *)malloc(array_mult_safe(sizeof(type), (n), 0))); \
2003#define ALLOC_ARRAY_GC(dptr, type, n, gc) \
2005 (dptr) = (type *)gc_malloc(array_mult_safe(sizeof(type), (n), 0), false, (gc)); \
2015#define ALLOC_ARRAY_CLEAR(dptr, type, n) \
2017 ALLOC_ARRAY(dptr, type, n); \
2018 memset((dptr), 0, (array_mult_safe(sizeof(type), (n), 0))); \
2029#define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc) \
2031 (dptr) = (type *)gc_malloc(array_mult_safe(sizeof(type), (n), 0), true, (gc)); \
2046#define ALLOC_VAR_ARRAY_CLEAR_GC(dptr, type, atype, n, gc) \
2048 (dptr) = (type *)gc_malloc(array_mult_safe(sizeof(atype), (n), sizeof(type)), true, (gc)); \
2058#define ALLOC_OBJ_GC(dptr, type, gc) \
2060 (dptr) = (type *)gc_malloc(sizeof(type), false, (gc)); \
2070#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc) \
2072 (dptr) = (type *)gc_malloc(sizeof(type), true, (gc)); \
bool buffer_list_defined(const struct buffer_list *ol)
Checks if the list is valid and non-empty.
static uint8_t * buf_bend(const struct buffer *buf)
Return a pointer one past the end of the buffer content.
bool buf_string_compare_advance(struct buffer *src, const char *match)
Compare the head of src with match and advance past it if equal.
static bool buf_write_u16(struct buffer *dest, uint16_t data)
Append a uint16_t to a buffer in network byte order.
static bool has_digit(const char *src)
Return true if the string contains at least one decimal digit.
static uint8_t * buf_bptr(const struct buffer *buf)
Return a pointer to the start of the buffer content.
static void gc_detach(struct gc_arena *a)
Detach all allocations from an arena without freeing them.
struct buffer_entry * buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
Allocates and appends a new buffer containing data of length size.
void rm_trailing_chars(char *str, const char *what_to_delete)
Remove all trailing characters that appear in a given set.
void string_null_terminate(char *str, int len, int capacity)
Null-terminate a fixed-length string buffer.
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
void buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len, const char *sep)
Aggregates as many buffers as possible from bl in a new buffer of maximum length max_len .
static bool buf_size_valid(const size_t size)
Return true iff size is within the allowed buffer size range.
void buf_clear(struct buffer *buf)
Zeroise and reset a buffer.
void buffer_list_reset(struct buffer_list *ol)
Empty the list ol and frees all the contained buffers.
const char * skip_leading_whitespace(const char *str)
Return a pointer past any leading whitespace in a string.
void buffer_list_aggregate(struct buffer_list *bl, const size_t max)
Aggregates as many buffers as possible from bl in a new buffer of maximum length max_len .
struct buffer clone_buf(const struct buffer *buf)
Duplicate a buffer, including its content.
void x_gc_freespecial(struct gc_arena *a)
Free all specially-allocated entries in a garbage collection arena.
bool buffer_write_file(const char *filename, const struct buffer *buf)
Write buffer contents to file.
static uint8_t * buf_blast(const struct buffer *buf)
Return a pointer to the last byte of the buffer content.
void buf_catrunc(struct buffer *buf, const char *str)
Append a string to the physical end of a buffer that was truncated by buf_printf().
static bool buf_init_dowork(struct buffer *buf, int offset)
Initialise a buffer with a given initial offset.
void buffer_list_pop(struct buffer_list *ol)
Remove and free the head buffer of the list.
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
void string_replace_leading(char *str, const char match, const char replace)
Replace all leading occurrences of a character in a string.
static struct buffer clear_buf(void)
Return an empty, undefined struct buffer (all fields zero).
bool buf_puts(struct buffer *buf, const char *str)
Append a string to a buffer with overflow check.
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Copy the content of one buffer to the end of another.
char * buf_extract_field(struct buffer *buf, char sep, struct gc_arena *gc)
Extract a field from buf that ends with the sep character.
#define BPTR(buf)
Return a pointer to the start of the buffer content.
static bool buf_write_u32(struct buffer *dest, uint32_t data)
Append a uint32_t to a buffer in network byte order.
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
Read a file into a buffer list, one buffer per line.
static bool buf_copy_excess(struct buffer *dest, struct buffer *src, int len)
Truncate src to len bytes and copy any excess to dest.
static bool buf_write_prepend(struct buffer *dest, const void *src, int size)
Prepend data to a buffer.
void string_clear(char *str)
Securely clear a null-terminated string.
static int buf_peek_u8(struct buffer *buf)
Return the first byte of the buffer without consuming it.
static bool buf_string_match(const struct buffer *src, const void *match, int size)
Compare src buffer contents with match.
static bool buf_size_valid_signed(const int size)
Return true iff a signed size is within the allowed buffer size range.
static int buf_read_u16(struct buffer *buf)
Read and consume a uint16_t from the front of a buffer.
static bool buf_safe_bidir(const struct buffer *buf, int len)
Check whether len bytes can be added to or removed from a buffer.
static bool buf_inc_len(struct buffer *buf, int inc)
Increase or decrease the length of a buffer.
static bool buf_copy_n(struct buffer *dest, struct buffer *src, int n)
Read n bytes from src and append them to dest.
static bool buf_equal(const struct buffer *a, const struct buffer *b)
Return true if buffer contents are equal.
static bool buf_string_match_head(const struct buffer *src, const void *match, int size)
Compare first size bytes of src buffer contents with match.
static bool buf_valid(const struct buffer *buf)
Return true iff buf is valid.
void gc_transfer(struct gc_arena *dest, struct gc_arena *src)
Move all allocations from one garbage collection arena to another.
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Test whether all characters in a string satisfy a character class filter.
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Format a NULL-terminated argument vector as a single string.
void buf_null_terminate(struct buffer *buf)
Force a null terminator at the end of the buffer content.
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Return a sub-buffer of another buffer.
static void gc_init(struct gc_arena *a)
Initialise a garbage collection arena to an empty state.
void * gc_realloc(void *ptr, size_t size, struct gc_arena *a)
allows to realloc a pointer previously allocated by gc_malloc or gc_realloc
static uint8_t * buf_read_alloc(struct buffer *buf, int size)
Consume bytes from the front of a buffer for reading.
static void buf_reset(struct buffer *buf)
Reset a buffer to an undefined (unallocated) state.
static bool buf_safe(const struct buffer *buf, size_t len)
Check whether len bytes can be appended to a buffer.
struct buffer_list * buffer_list_new(void)
Allocate an empty buffer list of capacity max_size.
static void buf_set_write(struct buffer *buf, uint8_t *data, int size)
Initialise a buffer with an externally provided writable memory region.
void chomp(char *str)
Remove trailing newline and carriage-return characters from a string.
struct buffer * buffer_list_peek(struct buffer_list *ol)
Retrieve the head buffer.
static bool buf_read(struct buffer *src, void *dest, int size)
Read bytes from the front of a buffer into a caller-supplied destination.
const char * np(const char *str)
Return a printable representation of a string that might be NULL.
bool string_check_buf(struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive)
Check a buffer if it only consists of allowed characters.
bool string_defined_equal(const char *s1, const char *s2)
#define BUF_SIZE_MAX
Maximum allowed size (in bytes) for a single buffer allocation.
size_t array_mult_safe(const size_t m1, const size_t m2, const size_t extra)
Safely compute the product of two sizes plus an extra amount.
static uint8_t * buf_prepend(struct buffer *buf, ssize_t size)
Make space at the front of a buffer for prepending data.
static int buf_len(const struct buffer *buf)
Return the length of the buffer content.
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Initialise a buffer with an externally provided read-only memory region.
static uint64_t buf_read_u64(struct buffer *buf, bool *good)
Read and consume a uint64_t from the front of a buffer.
static int buf_forward_capacity(const struct buffer *buf)
Return the number of bytes that can still be appended to the buffer.
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
static uint8_t * buf_write_alloc(struct buffer *buf, size_t size)
Reserve space at the end of a buffer for writing.
static bool buf_advance(struct buffer *buf, ssize_t size)
Advance the content start of a buffer, consuming bytes from the front.
bool buf_assign(struct buffer *dest, const struct buffer *src)
Assign the content of one buffer to another.
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
char * format_hex_ex(const uint8_t *data, size_t size, size_t maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Format a binary buffer as a hex string.
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
const char * string_mod_const(const char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace, struct gc_arena *gc)
Returns a copy of a string with certain classes of characters of it replaced with a specified charact...
static bool gc_defined(struct gc_arena *a)
Return true iff the arena contains at least one allocation.
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
Register an address with a custom free function in a garbage collection arena.
void buffer_list_advance(struct buffer_list *ol, ssize_t n)
Advance past n bytes in the head buffer, popping it if it becomes empty.
int string_array_len(const char **array)
Return the number of elements in a NULL-terminated array of strings.
static int buf_read_u8(struct buffer *buf)
Read and consume a uint8_t from the front of a buffer.
#define BLEN(buf)
Return the length of the buffer content in bytes.
static void buf_reset_len(struct buffer *buf)
Reset the length and offset of a buffer to zero.
static char * format_hex(const uint8_t *data, size_t size, size_t maxoutput, struct gc_arena *gc)
Format a binary buffer as a hex string with spaces every 4 bytes.
struct buffer buffer_read_from_file(const char *filename, struct gc_arena *gc)
buffer_read_from_file - copy the content of a file into a buffer
void buf_rmtail(struct buffer *buf, uint8_t remove)
Remove all occurrences of a specific byte from the end of a buffer.
char * string_substitute(const char *src, char from, char to, struct gc_arena *gc)
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Extract the next token from a buffer, delimited by a given character.
#define BLENZ(buf)
Return the length of the buffer content as a size_t.
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
void buf_size_error(const size_t size)
Report a buffer size error and abort.
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
static void strncpynt(char *dest, const char *src, size_t maxlen)
Like strncpy() but always null-terminates the destination.
static void gc_reset(struct gc_arena *a)
Free all allocations in a garbage collection arena and reinitialise it.
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
static bool buf_copy_range(struct buffer *dest, int dest_index, const struct buffer *src, int src_index, int src_len)
Copy a range of bytes from one buffer into a specific position in another.
static char * buf_str(const struct buffer *buf)
Return the buffer content pointer cast to char *.
struct buffer string_alloc_buf(const char *str, struct gc_arena *gc)
Allocate a buffer containing a copy of the given string.
static bool buf_defined(const struct buffer *buf)
Return true iff buf has a non-NULL data pointer.
void buffer_list_push(struct buffer_list *ol, const char *str)
Allocates and appends a new buffer containing str as data to ol.
void x_gc_free(struct gc_arena *a)
Free all plain allocations in a garbage collection arena.
void buf_chomp(struct buffer *buf)
Remove trailing newline and carriage-return characters from a buffer.
static int buf_reverse_capacity(const struct buffer *buf)
Return the number of bytes available for prepending to the buffer.
bool char_class(const unsigned char c, const unsigned int flags)
Test whether a character belongs to one or more character classes.
static bool strprefix(const char *str, const char *prefix)
Return true iff str starts with prefix.
bool buf_string_match_head_str(const struct buffer *src, const char *match)
Return true if the head of src matches the string match.
static uint32_t buf_read_u32(struct buffer *buf, bool *good)
Read and consume a uint32_t from the front of a buffer.
static void gc_freeaddrinfo_callback(void *addr)
Callback to free a struct addrinfo, suitable for use with gc_addspecial().
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
int buf_substring_len(const struct buffer *buf, int delim)
Return the number of bytes in a buffer up to and including a delimiter.
static bool buf_write_u64(struct buffer *dest, uint64_t data)
Append a uint64_t to a buffer in network byte order.
static int buf_forward_capacity_total(const struct buffer *buf)
Return the total number of bytes available from the current offset to the end of the allocated memory...
One node in a buffer_list linked list.
struct buffer_entry * next
Pointer to the next node, or NULL.
struct buffer buf
The buffer stored in this list node.
A singly-linked list of buffers, with head/tail pointers for O(1) push.
size_t size
Current number of entries.
struct buffer_entry * tail
Last item pushed.
size_t max_size
Maximum number of entries allowed.
struct buffer_entry * head
Next item to pop/peek.
Wrapper structure for dynamically allocated memory.
int capacity
Size in bytes of memory allocated by malloc().
uint8_t * data
Pointer to the allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
int offset
Offset in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
struct gc_entry_special * list_special
First element of the linked list of gc_entry_special structures for allocations requiring a custom fr...
struct gc_entry * list
First element of the linked list of gc_entry structures.
Garbage collection entry for a specially allocated structure that needs a custom free function to be ...
struct gc_entry_special * next
Garbage collection entry for one dynamically allocated block of memory.
struct gc_entry * next
Pointer to the next item in the linked list.