diff options
Diffstat (limited to 'src/openvpn/buffer.c')
-rw-r--r-- | src/openvpn/buffer.c | 1451 |
1 files changed, 806 insertions, 645 deletions
diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index 6af8dbb..2defd18 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -39,216 +39,230 @@ #include "memdbg.h" size_t -array_mult_safe (const size_t m1, const size_t m2, const size_t extra) +array_mult_safe(const size_t m1, const size_t m2, const size_t extra) { - const size_t limit = 0xFFFFFFFF; - unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra; - if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit)) - msg (M_FATAL, "attemped allocation of excessively large array"); - return (size_t) res; + const size_t limit = 0xFFFFFFFF; + unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra; + if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit)) + { + msg(M_FATAL, "attemped allocation of excessively large array"); + } + return (size_t) res; } void -buf_size_error (const size_t size) +buf_size_error(const size_t size) { - msg (M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size); + msg(M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size); } struct buffer #ifdef DMALLOC -alloc_buf_debug (size_t size, const char *file, int line) +alloc_buf_debug(size_t size, const char *file, int line) #else -alloc_buf (size_t size) +alloc_buf(size_t size) #endif { - struct buffer buf; + struct buffer buf; - if (!buf_size_valid (size)) - buf_size_error (size); - buf.capacity = (int)size; - buf.offset = 0; - buf.len = 0; + if (!buf_size_valid(size)) + { + buf_size_error(size); + } + buf.capacity = (int)size; + buf.offset = 0; + buf.len = 0; #ifdef DMALLOC - buf.data = openvpn_dmalloc (file, line, size); + buf.data = openvpn_dmalloc(file, line, size); #else - buf.data = calloc (1, size); + buf.data = calloc(1, size); #endif - check_malloc_return(buf.data); + check_malloc_return(buf.data); - return buf; + return buf; } struct buffer #ifdef DMALLOC -alloc_buf_gc_debug (size_t size, struct gc_arena *gc, const char *file, int line) +alloc_buf_gc_debug(size_t size, struct gc_arena *gc, const char *file, int line) #else -alloc_buf_gc (size_t size, struct gc_arena *gc) +alloc_buf_gc(size_t size, struct gc_arena *gc) #endif { - struct buffer buf; - if (!buf_size_valid (size)) - buf_size_error (size); - buf.capacity = (int)size; - buf.offset = 0; - buf.len = 0; + struct buffer buf; + if (!buf_size_valid(size)) + { + buf_size_error(size); + } + buf.capacity = (int)size; + buf.offset = 0; + buf.len = 0; #ifdef DMALLOC - buf.data = (uint8_t *) gc_malloc_debug (size, false, gc, file, line); + buf.data = (uint8_t *) gc_malloc_debug(size, false, gc, file, line); #else - buf.data = (uint8_t *) gc_malloc (size, false, gc); + buf.data = (uint8_t *) gc_malloc(size, false, gc); #endif - if (size) - *buf.data = 0; - return buf; + if (size) + { + *buf.data = 0; + } + return buf; } struct buffer #ifdef DMALLOC -clone_buf_debug (const struct buffer* buf, const char *file, int line) +clone_buf_debug(const struct buffer *buf, const char *file, int line) #else -clone_buf (const struct buffer* buf) +clone_buf(const struct buffer *buf) #endif { - struct buffer ret; - ret.capacity = buf->capacity; - ret.offset = buf->offset; - ret.len = buf->len; + struct buffer ret; + ret.capacity = buf->capacity; + ret.offset = buf->offset; + ret.len = buf->len; #ifdef DMALLOC - ret.data = (uint8_t *) openvpn_dmalloc (file, line, buf->capacity); + ret.data = (uint8_t *) openvpn_dmalloc(file, line, buf->capacity); #else - ret.data = (uint8_t *) malloc (buf->capacity); + ret.data = (uint8_t *) malloc(buf->capacity); #endif - check_malloc_return (ret.data); - memcpy (BPTR (&ret), BPTR (buf), BLEN (buf)); - return ret; + check_malloc_return(ret.data); + memcpy(BPTR(&ret), BPTR(buf), BLEN(buf)); + return ret; } #ifdef BUF_INIT_TRACKING bool -buf_init_debug (struct buffer *buf, int offset, const char *file, int line) +buf_init_debug(struct buffer *buf, int offset, const char *file, int line) { - buf->debug_file = file; - buf->debug_line = line; - return buf_init_dowork (buf, offset); + buf->debug_file = file; + buf->debug_line = line; + return buf_init_dowork(buf, offset); } static inline int -buf_debug_line (const struct buffer *buf) +buf_debug_line(const struct buffer *buf) { - return buf->debug_line; + return buf->debug_line; } static const char * -buf_debug_file (const struct buffer *buf) +buf_debug_file(const struct buffer *buf) { - return buf->debug_file; + return buf->debug_file; } -#else +#else /* ifdef BUF_INIT_TRACKING */ #define buf_debug_line(buf) 0 #define buf_debug_file(buf) "[UNDEF]" -#endif +#endif /* ifdef BUF_INIT_TRACKING */ void -buf_clear (struct buffer *buf) +buf_clear(struct buffer *buf) { - if (buf->capacity > 0) + if (buf->capacity > 0) { - secure_memzero (buf->data, buf->capacity); + secure_memzero(buf->data, buf->capacity); } - buf->len = 0; - buf->offset = 0; + buf->len = 0; + buf->offset = 0; } bool -buf_assign (struct buffer *dest, const struct buffer *src) +buf_assign(struct buffer *dest, const struct buffer *src) { - if (!buf_init (dest, src->offset)) - return false; - return buf_write (dest, BPTR (src), BLEN (src)); + if (!buf_init(dest, src->offset)) + { + return false; + } + return buf_write(dest, BPTR(src), BLEN(src)); } struct buffer -clear_buf () +clear_buf() { - struct buffer buf; - CLEAR (buf); - return buf; + struct buffer buf; + CLEAR(buf); + return buf; } void -free_buf (struct buffer *buf) +free_buf(struct buffer *buf) { - if (buf->data) - free (buf->data); - CLEAR (*buf); + if (buf->data) + { + free(buf->data); + } + CLEAR(*buf); } /* * Return a buffer for write that is a subset of another buffer */ struct buffer -buf_sub (struct buffer *buf, int size, bool prepend) +buf_sub(struct buffer *buf, int size, bool prepend) { - struct buffer ret; - uint8_t *data; + struct buffer ret; + uint8_t *data; - CLEAR (ret); - data = prepend ? buf_prepend (buf, size) : buf_write_alloc (buf, size); - if (data) + CLEAR(ret); + data = prepend ? buf_prepend(buf, size) : buf_write_alloc(buf, size); + if (data) { - ret.capacity = size; - ret.data = data; + ret.capacity = size; + ret.data = data; } - return ret; + return ret; } /* * printf append to a buffer with overflow check */ bool -buf_printf (struct buffer *buf, const char *format, ...) +buf_printf(struct buffer *buf, const char *format, ...) { - int ret = false; - if (buf_defined (buf)) - { - va_list arglist; - uint8_t *ptr = BEND (buf); - int cap = buf_forward_capacity (buf); - - if (cap > 0) - { - int stat; - va_start (arglist, format); - stat = vsnprintf ((char *)ptr, cap, format, arglist); - va_end (arglist); - *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ - buf->len += (int) strlen ((char *)ptr); - if (stat >= 0 && stat < cap) - ret = true; - } - } - return ret; + int ret = false; + if (buf_defined(buf)) + { + va_list arglist; + uint8_t *ptr = BEND(buf); + int cap = buf_forward_capacity(buf); + + if (cap > 0) + { + int stat; + va_start(arglist, format); + stat = vsnprintf((char *)ptr, cap, format, arglist); + va_end(arglist); + *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ + buf->len += (int) strlen((char *)ptr); + if (stat >= 0 && stat < cap) + { + ret = true; + } + } + } + return ret; } bool buf_puts(struct buffer *buf, const char *str) { - int ret = false; - uint8_t *ptr = BEND (buf); - int cap = buf_forward_capacity (buf); - if (cap > 0) + int ret = false; + uint8_t *ptr = BEND(buf); + int cap = buf_forward_capacity(buf); + if (cap > 0) { - strncpynt ((char *)ptr,str, cap); - *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ - buf->len += (int) strlen ((char *)ptr); - ret = true; + strncpynt((char *)ptr,str, cap); + *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ + buf->len += (int) strlen((char *)ptr); + ret = true; } - return ret; + return ret; } - + /* * This is necessary due to certain buggy implementations of snprintf, @@ -260,18 +274,19 @@ buf_puts(struct buffer *buf, const char *str) * Any modifications here should be done to the other place as well. */ -bool openvpn_snprintf(char *str, size_t size, const char *format, ...) +bool +openvpn_snprintf(char *str, size_t size, const char *format, ...) { - va_list arglist; - int len = -1; - if (size > 0) + va_list arglist; + int len = -1; + if (size > 0) { - va_start (arglist, format); - len = vsnprintf (str, size, format, arglist); - va_end (arglist); - str[size - 1] = 0; + va_start(arglist, format); + len = vsnprintf(str, size, format, arglist); + va_end(arglist); + str[size - 1] = 0; } - return (len >= 0 && len < size); + return (len >= 0 && len < size); } /* @@ -279,15 +294,15 @@ bool openvpn_snprintf(char *str, size_t size, const char *format, ...) * truncated by buf_printf */ void -buf_catrunc (struct buffer *buf, const char *str) +buf_catrunc(struct buffer *buf, const char *str) { - if (buf_forward_capacity (buf) <= 1) + if (buf_forward_capacity(buf) <= 1) { - int len = (int) strlen (str) + 1; - if (len < buf_forward_capacity_total (buf)) - { - strncpynt ((char *)(buf->data + buf->capacity - len), str, len); - } + int len = (int) strlen(str) + 1; + if (len < buf_forward_capacity_total(buf)) + { + strncpynt((char *)(buf->data + buf->capacity - len), str, len); + } } } @@ -295,26 +310,30 @@ buf_catrunc (struct buffer *buf, const char *str) * convert a multi-line output to one line */ void -convert_to_one_line (struct buffer *buf) +convert_to_one_line(struct buffer *buf) { - uint8_t *cp = BPTR(buf); - int len = BLEN(buf); - while (len--) + uint8_t *cp = BPTR(buf); + int len = BLEN(buf); + while (len--) { - if (*cp == '\n') - *cp = '|'; - ++cp; + if (*cp == '\n') + { + *cp = '|'; + } + ++cp; } } /* NOTE: requires that string be null terminated */ void -buf_write_string_file (const struct buffer *buf, const char *filename, int fd) +buf_write_string_file(const struct buffer *buf, const char *filename, int fd) { - const int len = strlen ((char *) BPTR (buf)); - const int size = write (fd, BPTR (buf), len); - if (size != len) - msg (M_ERR, "Write error on file '%s'", filename); + const int len = strlen((char *) BPTR(buf)); + const int size = write(fd, BPTR(buf), len); + if (size != len) + { + msg(M_ERR, "Write error on file '%s'", filename); + } } /* @@ -323,53 +342,53 @@ buf_write_string_file (const struct buffer *buf, const char *filename, int fd) void * #ifdef DMALLOC -gc_malloc_debug (size_t size, bool clear, struct gc_arena *a, const char *file, int line) +gc_malloc_debug(size_t size, bool clear, struct gc_arena *a, const char *file, int line) #else -gc_malloc (size_t size, bool clear, struct gc_arena *a) +gc_malloc(size_t size, bool clear, struct gc_arena *a) #endif { - void *ret; - if (a) + void *ret; + if (a) { - struct gc_entry *e; + struct gc_entry *e; #ifdef DMALLOC - e = (struct gc_entry *) openvpn_dmalloc (file, line, size + sizeof (struct gc_entry)); + e = (struct gc_entry *) openvpn_dmalloc(file, line, size + sizeof(struct gc_entry)); #else - e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry)); + e = (struct gc_entry *) malloc(size + sizeof(struct gc_entry)); #endif - check_malloc_return (e); - ret = (char *) e + sizeof (struct gc_entry); - e->next = a->list; - a->list = e; + check_malloc_return(e); + ret = (char *) e + sizeof(struct gc_entry); + e->next = a->list; + a->list = e; } - else + else { #ifdef DMALLOC - ret = openvpn_dmalloc (file, line, size); + ret = openvpn_dmalloc(file, line, size); #else - ret = malloc (size); + ret = malloc(size); #endif - check_malloc_return (ret); + check_malloc_return(ret); } #ifndef ZERO_BUFFER_ON_ALLOC - if (clear) + if (clear) #endif - memset (ret, 0, size); - return ret; + memset(ret, 0, size); + return ret; } void -x_gc_free (struct gc_arena *a) +x_gc_free(struct gc_arena *a) { - struct gc_entry *e; - e = a->list; - a->list = NULL; - - while (e != NULL) + struct gc_entry *e; + e = a->list; + a->list = NULL; + + while (e != NULL) { - struct gc_entry *next = e->next; - free (e); - e = next; + struct gc_entry *next = e->next; + free(e); + e = next; } } @@ -378,36 +397,37 @@ x_gc_free (struct gc_arena *a) */ void -x_gc_freespecial (struct gc_arena *a) +x_gc_freespecial(struct gc_arena *a) { - struct gc_entry_special *e; - e = a->list_special; - a->list_special = NULL; + struct gc_entry_special *e; + e = a->list_special; + a->list_special = NULL; - while (e != NULL) + while (e != NULL) { - struct gc_entry_special *next = e->next; - e->free_fnc (e->addr); - free(e); - e = next; + struct gc_entry_special *next = e->next; + e->free_fnc(e->addr); + free(e); + e = next; } } -void gc_addspecial (void *addr, void (free_function)(void*), struct gc_arena *a) +void +gc_addspecial(void *addr, void(free_function)(void *), struct gc_arena *a) { - ASSERT(a); - struct gc_entry_special *e; + ASSERT(a); + struct gc_entry_special *e; #ifdef DMALLOC - e = (struct gc_entry_special *) openvpn_dmalloc (file, line, sizeof (struct gc_entry_special)); + e = (struct gc_entry_special *) openvpn_dmalloc(file, line, sizeof(struct gc_entry_special)); #else - e = (struct gc_entry_special *) malloc (sizeof (struct gc_entry_special)); + e = (struct gc_entry_special *) malloc(sizeof(struct gc_entry_special)); #endif - check_malloc_return (e); - e->free_fnc = free_function; - e->addr = addr; + check_malloc_return(e); + e->free_fnc = free_function; + e->addr = addr; - e->next = a->list_special; - a->list_special = e; + e->next = a->list_special; + a->list_special = e; } @@ -415,19 +435,19 @@ void gc_addspecial (void *addr, void (free_function)(void*), struct gc_arena *a) * Transfer src arena to dest, resetting src to an empty arena. */ void -gc_transfer (struct gc_arena *dest, struct gc_arena *src) +gc_transfer(struct gc_arena *dest, struct gc_arena *src) { - if (dest && src) - { - struct gc_entry *e = src->list; - if (e) - { - while (e->next != NULL) - e = e->next; - e->next = dest->list; - dest->list = src->list; - src->list = NULL; - } + if (dest && src) + { + struct gc_entry *e = src->list; + if (e) + { + while (e->next != NULL) + e = e->next; + e->next = dest->list; + dest->list = src->list; + src->list = NULL; + } } } @@ -436,28 +456,34 @@ gc_transfer (struct gc_arena *dest, struct gc_arena *src) */ char * -format_hex_ex (const uint8_t *data, int size, int maxoutput, - unsigned int space_break_flags, const char* separator, - struct gc_arena *gc) +format_hex_ex(const uint8_t *data, int size, int maxoutput, + unsigned int space_break_flags, const char *separator, + struct gc_arena *gc) { - const size_t bytes_per_hexblock = space_break_flags & FHE_SPACE_BREAK_MASK; - const size_t separator_len = separator ? strlen (separator) : 0; - static_assert (INT_MAX <= SIZE_MAX, "Code assumes INT_MAX <= SIZE_MAX"); - const size_t out_len = maxoutput > 0 ? maxoutput : - ((size * 2) + ((size / bytes_per_hexblock) * separator_len) + 2); - - struct buffer out = alloc_buf_gc (out_len, gc); - for (int i = 0; i < size; ++i) - { - if (separator && i && !(i % bytes_per_hexblock)) - buf_printf (&out, "%s", separator); - if (space_break_flags & FHE_CAPS) - buf_printf (&out, "%02X", data[i]); - else - buf_printf (&out, "%02x", data[i]); - } - buf_catrunc (&out, "[more...]"); - return (char *)out.data; + const size_t bytes_per_hexblock = space_break_flags & FHE_SPACE_BREAK_MASK; + const size_t separator_len = separator ? strlen(separator) : 0; + static_assert(INT_MAX <= SIZE_MAX, "Code assumes INT_MAX <= SIZE_MAX"); + const size_t out_len = maxoutput > 0 ? maxoutput : + ((size * 2) + ((size / bytes_per_hexblock) * separator_len) + 2); + + struct buffer out = alloc_buf_gc(out_len, gc); + for (int i = 0; i < size; ++i) + { + if (separator && i && !(i % bytes_per_hexblock)) + { + buf_printf(&out, "%s", separator); + } + if (space_break_flags & FHE_CAPS) + { + buf_printf(&out, "%02X", data[i]); + } + else + { + buf_printf(&out, "%02x", data[i]); + } + } + buf_catrunc(&out, "[more...]"); + return (char *)out.data; } /* @@ -465,13 +491,13 @@ format_hex_ex (const uint8_t *data, int size, int maxoutput, */ void -buf_rmtail (struct buffer *buf, uint8_t remove) +buf_rmtail(struct buffer *buf, uint8_t remove) { - uint8_t *cp = BLAST(buf); - if (cp && *cp == remove) + uint8_t *cp = BLAST(buf); + if (cp && *cp == remove) { - *cp = '\0'; - --buf->len; + *cp = '\0'; + --buf->len; } } @@ -480,16 +506,20 @@ buf_rmtail (struct buffer *buf, uint8_t remove) * truncation of the last char. */ void -buf_null_terminate (struct buffer *buf) +buf_null_terminate(struct buffer *buf) { - char *last = (char *) BLAST (buf); - if (last && *last == '\0') /* already terminated? */ - return; + char *last = (char *) BLAST(buf); + if (last && *last == '\0') /* already terminated? */ + { + return; + } - if (!buf_safe (buf, 1)) /* make space for trailing null */ - buf_inc_len (buf, -1); + if (!buf_safe(buf, 1)) /* make space for trailing null */ + { + buf_inc_len(buf, -1); + } - buf_write_u8 (buf, 0); + buf_write_u8(buf, 0); } /* @@ -497,79 +527,91 @@ buf_null_terminate (struct buffer *buf) * null termination. */ void -buf_chomp (struct buffer *buf) +buf_chomp(struct buffer *buf) { - while (true) - { - char *last = (char *) BLAST (buf); - if (!last) - break; - if (char_class (*last, CC_CRLF|CC_NULL)) - { - if (!buf_inc_len (buf, -1)) - break; - } - else - break; - } - buf_null_terminate (buf); + while (true) + { + char *last = (char *) BLAST(buf); + if (!last) + { + break; + } + if (char_class(*last, CC_CRLF|CC_NULL)) + { + if (!buf_inc_len(buf, -1)) + { + break; + } + } + else + { + break; + } + } + buf_null_terminate(buf); } const char * -skip_leading_whitespace (const char *str) +skip_leading_whitespace(const char *str) { - while (*str) + while (*str) { - const char c = *str; - if (!(c == ' ' || c == '\t')) - break; - ++str; + const char c = *str; + if (!(c == ' ' || c == '\t')) + { + break; + } + ++str; } - return str; + return str; } /* * like buf_null_terminate, but operate on strings */ void -string_null_terminate (char *str, int len, int capacity) +string_null_terminate(char *str, int len, int capacity) { - ASSERT (len >= 0 && len <= capacity && capacity > 0); - if (len < capacity) - *(str + len) = '\0'; - else if (len == capacity) - *(str + len - 1) = '\0'; + ASSERT(len >= 0 && len <= capacity && capacity > 0); + if (len < capacity) + { + *(str + len) = '\0'; + } + else if (len == capacity) + { + *(str + len - 1) = '\0'; + } } /* * Remove trailing \r and \n chars. */ void -chomp (char *str) +chomp(char *str) { - rm_trailing_chars (str, "\r\n"); + rm_trailing_chars(str, "\r\n"); } /* * Remove trailing chars */ void -rm_trailing_chars (char *str, const char *what_to_delete) +rm_trailing_chars(char *str, const char *what_to_delete) { - bool modified; - do { - const int len = strlen (str); - modified = false; - if (len > 0) - { - char *cp = str + (len - 1); - if (strchr (what_to_delete, *cp) != NULL) - { - *cp = '\0'; - modified = true; - } - } - } while (modified); + bool modified; + do { + const int len = strlen(str); + modified = false; + if (len > 0) + { + char *cp = str + (len - 1); + if (strchr(what_to_delete, *cp) != NULL) + { + *cp = '\0'; + modified = true; + } + } + } while (modified); } /* @@ -577,51 +619,56 @@ rm_trailing_chars (char *str, const char *what_to_delete) */ char * #ifdef DMALLOC -string_alloc_debug (const char *str, struct gc_arena *gc, const char *file, int line) +string_alloc_debug(const char *str, struct gc_arena *gc, const char *file, int line) #else -string_alloc (const char *str, struct gc_arena *gc) +string_alloc(const char *str, struct gc_arena *gc) #endif { - if (str) + if (str) { - const int n = strlen (str) + 1; - char *ret; + const int n = strlen(str) + 1; + char *ret; - if (gc) { + if (gc) + { #ifdef DMALLOC - ret = (char *) gc_malloc_debug (n, false, gc, file, line); + ret = (char *) gc_malloc_debug(n, false, gc, file, line); #else - ret = (char *) gc_malloc (n, false, gc); + ret = (char *) gc_malloc(n, false, gc); #endif - } else { - /* If there are no garbage collector available, it's expected - * that the caller cleans up afterwards. This is coherent with the - * earlier behaviour when gc_malloc() would be called with gc == NULL - */ + } + else + { + /* If there are no garbage collector available, it's expected + * that the caller cleans up afterwards. This is coherent with the + * earlier behaviour when gc_malloc() would be called with gc == NULL + */ #ifdef DMALLOC - ret = openvpn_dmalloc (file, line, n); - memset(ret, 0, n); + ret = openvpn_dmalloc(file, line, n); + memset(ret, 0, n); #else - ret = calloc(1, n); + ret = calloc(1, n); #endif - check_malloc_return(ret); - } - memcpy (ret, str, n); - return ret; + check_malloc_return(ret); + } + memcpy(ret, str, n); + return ret; + } + else + { + return NULL; } - else - return NULL; } /* * Erase all characters in a string */ void -string_clear (char *str) +string_clear(char *str) { - if (str) + if (str) { - secure_memzero (str, strlen (str)); + secure_memzero(str, strlen(str)); } } @@ -629,36 +676,44 @@ string_clear (char *str) * Return the length of a string array */ int -string_array_len (const char **array) +string_array_len(const char **array) { - int i = 0; - if (array) + int i = 0; + if (array) { - while (array[i]) - ++i; + while (array[i]) + ++i; } - return i; + return i; } char * -print_argv (const char **p, struct gc_arena *gc, const unsigned int flags) +print_argv(const char **p, struct gc_arena *gc, const unsigned int flags) { - struct buffer out = alloc_buf_gc (256, gc); - int i = 0; - for (;;) - { - const char *cp = *p++; - if (!cp) - break; - if (i) - buf_printf (&out, " "); - if (flags & PA_BRACKET) - buf_printf (&out, "[%s]", cp); - else - buf_printf (&out, "%s", cp); - ++i; - } - return BSTR (&out); + struct buffer out = alloc_buf_gc(256, gc); + int i = 0; + for (;; ) + { + const char *cp = *p++; + if (!cp) + { + break; + } + if (i) + { + buf_printf(&out, " "); + } + if (flags & PA_BRACKET) + { + buf_printf(&out, "[%s]", cp); + } + else + { + buf_printf(&out, "%s", cp); + } + ++i; + } + return BSTR(&out); } /* @@ -666,25 +721,27 @@ print_argv (const char **p, struct gc_arena *gc, const unsigned int flags) */ struct buffer #ifdef DMALLOC -string_alloc_buf_debug (const char *str, struct gc_arena *gc, const char *file, int line) +string_alloc_buf_debug(const char *str, struct gc_arena *gc, const char *file, int line) #else -string_alloc_buf (const char *str, struct gc_arena *gc) +string_alloc_buf(const char *str, struct gc_arena *gc) #endif { - struct buffer buf; + struct buffer buf; - ASSERT (str); + ASSERT(str); #ifdef DMALLOC - buf_set_read (&buf, (uint8_t*) string_alloc_debug (str, gc, file, line), strlen (str) + 1); + buf_set_read(&buf, (uint8_t *) string_alloc_debug(str, gc, file, line), strlen(str) + 1); #else - buf_set_read (&buf, (uint8_t*) string_alloc (str, gc), strlen (str) + 1); + buf_set_read(&buf, (uint8_t *) string_alloc(str, gc), strlen(str) + 1); #endif - if (buf.len > 0) /* Don't count trailing '\0' as part of length */ - --buf.len; + if (buf.len > 0) /* Don't count trailing '\0' as part of length */ + { + --buf.len; + } - return buf; + return buf; } /* @@ -692,40 +749,46 @@ string_alloc_buf (const char *str, struct gc_arena *gc) */ bool -buf_string_match_head_str (const struct buffer *src, const char *match) +buf_string_match_head_str(const struct buffer *src, const char *match) { - const int size = strlen (match); - if (size < 0 || size > src->len) - return false; - return memcmp (BPTR (src), match, size) == 0; + const int size = strlen(match); + if (size < 0 || size > src->len) + { + return false; + } + return memcmp(BPTR(src), match, size) == 0; } bool -buf_string_compare_advance (struct buffer *src, const char *match) +buf_string_compare_advance(struct buffer *src, const char *match) { - if (buf_string_match_head_str (src, match)) + if (buf_string_match_head_str(src, match)) { - buf_advance (src, strlen (match)); - return true; + buf_advance(src, strlen(match)); + return true; + } + else + { + return false; } - else - return false; } int -buf_substring_len (const struct buffer *buf, int delim) +buf_substring_len(const struct buffer *buf, int delim) { - int i = 0; - struct buffer tmp = *buf; - int c; + int i = 0; + struct buffer tmp = *buf; + int c; - while ((c = buf_read_u8 (&tmp)) >= 0) + while ((c = buf_read_u8(&tmp)) >= 0) { - ++i; - if (c == delim) - return i; + ++i; + if (c == delim) + { + return i; + } } - return -1; + return -1; } /* @@ -733,41 +796,51 @@ buf_substring_len (const struct buffer *buf, int delim) */ bool -buf_parse (struct buffer *buf, const int delim, char *line, const int size) +buf_parse(struct buffer *buf, const int delim, char *line, const int size) { - bool eol = false; - int n = 0; - int c; + bool eol = false; + int n = 0; + int c; - ASSERT (size > 0); + ASSERT(size > 0); - do + do { - c = buf_read_u8 (buf); - if (c < 0) - eol = true; - if (c <= 0 || c == delim) - c = 0; - if (n >= size) - break; - line[n++] = c; + c = buf_read_u8(buf); + if (c < 0) + { + eol = true; + } + if (c <= 0 || c == delim) + { + c = 0; + } + if (n >= size) + { + break; + } + line[n++] = c; } - while (c); + while (c); - line[size-1] = '\0'; - return !(eol && !strlen (line)); + line[size-1] = '\0'; + return !(eol && !strlen(line)); } /* * Print a string which might be NULL */ const char * -np (const char *str) +np(const char *str) { - if (str) - return str; - else - return "[NULL]"; + if (str) + { + return str; + } + else + { + return "[NULL]"; + } } /* @@ -775,97 +848,163 @@ np (const char *str) */ bool -char_class (const unsigned char c, const unsigned int flags) +char_class(const unsigned char c, const unsigned int flags) { - if (!flags) - return false; - if (flags & CC_ANY) - return true; + if (!flags) + { + return false; + } + if (flags & CC_ANY) + { + return true; + } - if ((flags & CC_NULL) && c == '\0') - return true; + if ((flags & CC_NULL) && c == '\0') + { + return true; + } - if ((flags & CC_ALNUM) && isalnum (c)) - return true; - if ((flags & CC_ALPHA) && isalpha (c)) - return true; - if ((flags & CC_ASCII) && isascii (c)) - return true; - if ((flags & CC_CNTRL) && iscntrl (c)) - return true; - if ((flags & CC_DIGIT) && isdigit (c)) - return true; - if ((flags & CC_PRINT) && (c >= 32 && c != 127)) /* allow ascii non-control and UTF-8, consider DEL to be a control */ - return true; - if ((flags & CC_PUNCT) && ispunct (c)) - return true; - if ((flags & CC_SPACE) && isspace (c)) - return true; - if ((flags & CC_XDIGIT) && isxdigit (c)) - return true; + if ((flags & CC_ALNUM) && isalnum(c)) + { + return true; + } + if ((flags & CC_ALPHA) && isalpha(c)) + { + return true; + } + if ((flags & CC_ASCII) && isascii(c)) + { + return true; + } + if ((flags & CC_CNTRL) && iscntrl(c)) + { + return true; + } + if ((flags & CC_DIGIT) && isdigit(c)) + { + return true; + } + if ((flags & CC_PRINT) && (c >= 32 && c != 127)) /* allow ascii non-control and UTF-8, consider DEL to be a control */ + { + return true; + } + if ((flags & CC_PUNCT) && ispunct(c)) + { + return true; + } + if ((flags & CC_SPACE) && isspace(c)) + { + return true; + } + if ((flags & CC_XDIGIT) && isxdigit(c)) + { + return true; + } - if ((flags & CC_BLANK) && (c == ' ' || c == '\t')) - return true; - if ((flags & CC_NEWLINE) && c == '\n') - return true; - if ((flags & CC_CR) && c == '\r') - return true; + if ((flags & CC_BLANK) && (c == ' ' || c == '\t')) + { + return true; + } + if ((flags & CC_NEWLINE) && c == '\n') + { + return true; + } + if ((flags & CC_CR) && c == '\r') + { + return true; + } - if ((flags & CC_BACKSLASH) && c == '\\') - return true; - if ((flags & CC_UNDERBAR) && c == '_') - return true; - if ((flags & CC_DASH) && c == '-') - return true; - if ((flags & CC_DOT) && c == '.') - return true; - if ((flags & CC_COMMA) && c == ',') - return true; - if ((flags & CC_COLON) && c == ':') - return true; - if ((flags & CC_SLASH) && c == '/') - return true; - if ((flags & CC_SINGLE_QUOTE) && c == '\'') - return true; - if ((flags & CC_DOUBLE_QUOTE) && c == '\"') - return true; - if ((flags & CC_REVERSE_QUOTE) && c == '`') - return true; - if ((flags & CC_AT) && c == '@') - return true; - if ((flags & CC_EQUAL) && c == '=') - return true; - if ((flags & CC_LESS_THAN) && c == '<') - return true; - if ((flags & CC_GREATER_THAN) && c == '>') - return true; - if ((flags & CC_PIPE) && c == '|') - return true; - if ((flags & CC_QUESTION_MARK) && c == '?') - return true; - if ((flags & CC_ASTERISK) && c == '*') - return true; + if ((flags & CC_BACKSLASH) && c == '\\') + { + return true; + } + if ((flags & CC_UNDERBAR) && c == '_') + { + return true; + } + if ((flags & CC_DASH) && c == '-') + { + return true; + } + if ((flags & CC_DOT) && c == '.') + { + return true; + } + if ((flags & CC_COMMA) && c == ',') + { + return true; + } + if ((flags & CC_COLON) && c == ':') + { + return true; + } + if ((flags & CC_SLASH) && c == '/') + { + return true; + } + if ((flags & CC_SINGLE_QUOTE) && c == '\'') + { + return true; + } + if ((flags & CC_DOUBLE_QUOTE) && c == '\"') + { + return true; + } + if ((flags & CC_REVERSE_QUOTE) && c == '`') + { + return true; + } + if ((flags & CC_AT) && c == '@') + { + return true; + } + if ((flags & CC_EQUAL) && c == '=') + { + return true; + } + if ((flags & CC_LESS_THAN) && c == '<') + { + return true; + } + if ((flags & CC_GREATER_THAN) && c == '>') + { + return true; + } + if ((flags & CC_PIPE) && c == '|') + { + return true; + } + if ((flags & CC_QUESTION_MARK) && c == '?') + { + return true; + } + if ((flags & CC_ASTERISK) && c == '*') + { + return true; + } - return false; + return false; } static inline bool -char_inc_exc (const char c, const unsigned int inclusive, const unsigned int exclusive) +char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive) { - return char_class (c, inclusive) && !char_class (c, exclusive); + return char_class(c, inclusive) && !char_class(c, exclusive); } bool -string_class (const char *str, const unsigned int inclusive, const unsigned int exclusive) +string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive) { - char c; - ASSERT (str); - while ((c = *str++)) + char c; + ASSERT(str); + while ((c = *str++)) { - if (!char_inc_exc (c, inclusive, exclusive)) - return false; + if (!char_inc_exc(c, inclusive, exclusive)) + { + return false; + } } - return true; + return true; } /* @@ -873,63 +1012,71 @@ string_class (const char *str, const unsigned int inclusive, const unsigned int * Guaranteed to not increase string length. */ bool -string_mod (char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace) +string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace) { - const char *in = str; - bool ret = true; - - ASSERT (str); - - while (true) - { - char c = *in++; - if (c) - { - if (!char_inc_exc (c, inclusive, exclusive)) - { - c = replace; - ret = false; - } - if (c) - *str++ = c; - } - else - { - *str = '\0'; - break; - } - } - return ret; + const char *in = str; + bool ret = true; + + ASSERT(str); + + while (true) + { + char c = *in++; + if (c) + { + if (!char_inc_exc(c, inclusive, exclusive)) + { + c = replace; + ret = false; + } + if (c) + { + *str++ = c; + } + } + else + { + *str = '\0'; + break; + } + } + return ret; } const char * -string_mod_const (const char *str, - const unsigned int inclusive, - const unsigned int exclusive, - const char replace, - struct gc_arena *gc) +string_mod_const(const char *str, + const unsigned int inclusive, + const unsigned int exclusive, + const char replace, + struct gc_arena *gc) { - if (str) + if (str) { - char *buf = string_alloc (str, gc); - string_mod (buf, inclusive, exclusive, replace); - return buf; + char *buf = string_alloc(str, gc); + string_mod(buf, inclusive, exclusive, replace); + return buf; + } + else + { + return NULL; } - else - return NULL; } void -string_replace_leading (char *str, const char match, const char replace) +string_replace_leading(char *str, const char match, const char replace) { - ASSERT (match != '\0'); - while (*str) + ASSERT(match != '\0'); + while (*str) { - if (*str == match) - *str = replace; - else - break; - ++str; + if (*str == match) + { + *str = replace; + } + else + { + break; + } + ++str; } } @@ -940,14 +1087,14 @@ string_replace_leading (char *str, const char match, const char replace) #define CC_REPLACE ('.') void -character_class_debug (void) +character_class_debug(void) { - char buf[256]; + char buf[256]; - while (fgets (buf, sizeof (buf), stdin) != NULL) + while (fgets(buf, sizeof(buf), stdin) != NULL) { - string_mod (buf, CC_INCLUDE, CC_EXCLUDE, CC_REPLACE); - printf ("%s", buf); + string_mod(buf, CC_INCLUDE, CC_EXCLUDE, CC_REPLACE); + printf("%s", buf); } } @@ -955,214 +1102,228 @@ character_class_debug (void) #ifdef VERIFY_ALIGNMENT void -valign4 (const struct buffer *buf, const char *file, const int line) +valign4(const struct buffer *buf, const char *file, const int line) { - if (buf && buf->len) + if (buf && buf->len) { - int msglevel = D_ALIGN_DEBUG; - const unsigned int u = (unsigned int) BPTR (buf); - - if (u & (PAYLOAD_ALIGN-1)) - msglevel = D_ALIGN_ERRORS; - - msg (msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d", - (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "", - file, - line, - (ptr_type)buf->data, - buf->offset, - buf->len, - buf->capacity, - buf_debug_file (buf), - buf_debug_line (buf)); + int msglevel = D_ALIGN_DEBUG; + const unsigned int u = (unsigned int) BPTR(buf); + + if (u & (PAYLOAD_ALIGN-1)) + { + msglevel = D_ALIGN_ERRORS; + } + + msg(msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d", + (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "", + file, + line, + (ptr_type)buf->data, + buf->offset, + buf->len, + buf->capacity, + buf_debug_file(buf), + buf_debug_line(buf)); } } -#endif +#endif /* ifdef VERIFY_ALIGNMENT */ /* * struct buffer_list */ struct buffer_list * -buffer_list_new (const int max_size) +buffer_list_new(const int max_size) { - struct buffer_list *ret; - ALLOC_OBJ_CLEAR (ret, struct buffer_list); - ret->max_size = max_size; - ret->size = 0; - return ret; + struct buffer_list *ret; + ALLOC_OBJ_CLEAR(ret, struct buffer_list); + ret->max_size = max_size; + ret->size = 0; + return ret; } void -buffer_list_free (struct buffer_list *ol) +buffer_list_free(struct buffer_list *ol) { - if (ol) + if (ol) { - buffer_list_reset (ol); - free (ol); + buffer_list_reset(ol); + free(ol); } } bool -buffer_list_defined (const struct buffer_list *ol) +buffer_list_defined(const struct buffer_list *ol) { - return ol && ol->head != NULL; + return ol && ol->head != NULL; } void -buffer_list_reset (struct buffer_list *ol) +buffer_list_reset(struct buffer_list *ol) { - struct buffer_entry *e = ol->head; - while (e) + struct buffer_entry *e = ol->head; + while (e) { - struct buffer_entry *next = e->next; - free_buf (&e->buf); - free (e); - e = next; + struct buffer_entry *next = e->next; + free_buf(&e->buf); + free(e); + e = next; } - ol->head = ol->tail = NULL; - ol->size = 0; + ol->head = ol->tail = NULL; + ol->size = 0; } void -buffer_list_push (struct buffer_list *ol, const unsigned char *str) +buffer_list_push(struct buffer_list *ol, const unsigned char *str) { - if (str) + if (str) { - const size_t len = strlen ((const char *)str); - struct buffer_entry *e = buffer_list_push_data (ol, str, len+1); - if (e) - e->buf.len = len; /* Don't count trailing '\0' as part of length */ + const size_t len = strlen((const char *)str); + struct buffer_entry *e = buffer_list_push_data(ol, str, len+1); + if (e) + { + e->buf.len = len; /* Don't count trailing '\0' as part of length */ + } } } struct buffer_entry * -buffer_list_push_data (struct buffer_list *ol, const uint8_t *data, size_t size) +buffer_list_push_data(struct buffer_list *ol, const uint8_t *data, size_t size) { - struct buffer_entry *e = NULL; - if (data && (!ol->max_size || ol->size < ol->max_size)) - { - ALLOC_OBJ_CLEAR (e, struct buffer_entry); - - ++ol->size; - if (ol->tail) - { - ASSERT (ol->head); - ol->tail->next = e; - } - else - { - ASSERT (!ol->head); - ol->head = e; - } - e->buf = alloc_buf (size); - memcpy (e->buf.data, data, size); - e->buf.len = (int)size; - ol->tail = e; - } - return e; + struct buffer_entry *e = NULL; + if (data && (!ol->max_size || ol->size < ol->max_size)) + { + ALLOC_OBJ_CLEAR(e, struct buffer_entry); + + ++ol->size; + if (ol->tail) + { + ASSERT(ol->head); + ol->tail->next = e; + } + else + { + ASSERT(!ol->head); + ol->head = e; + } + e->buf = alloc_buf(size); + memcpy(e->buf.data, data, size); + e->buf.len = (int)size; + ol->tail = e; + } + return e; } struct buffer * -buffer_list_peek (struct buffer_list *ol) +buffer_list_peek(struct buffer_list *ol) { - if (ol && ol->head) - return &ol->head->buf; - else - return NULL; + if (ol && ol->head) + { + return &ol->head->buf; + } + else + { + return NULL; + } } void -buffer_list_aggregate_separator (struct buffer_list *bl, const size_t max, const char *sep) +buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max, const char *sep) { - int sep_len = strlen(sep); - - if (bl->head) - { - struct buffer_entry *more = bl->head; - size_t size = 0; - int count = 0; - for (count = 0; more && size <= max; ++count) - { - size += BLEN(&more->buf) + sep_len; - more = more->next; - } - - if (count >= 2) - { - int i; - struct buffer_entry *e = bl->head, *f; - - ALLOC_OBJ_CLEAR (f, struct buffer_entry); - f->buf.data = malloc (size); - check_malloc_return (f->buf.data); - f->buf.capacity = size; - for (i = 0; e && i < count; ++i) - { - struct buffer_entry *next = e->next; - buf_copy (&f->buf, &e->buf); - buf_write(&f->buf, sep, sep_len); - free_buf (&e->buf); - free (e); - e = next; - } - bl->head = f; - f->next = more; - if (!more) - bl->tail = f; - } + int sep_len = strlen(sep); + + if (bl->head) + { + struct buffer_entry *more = bl->head; + size_t size = 0; + int count = 0; + for (count = 0; more && size <= max; ++count) + { + size += BLEN(&more->buf) + sep_len; + more = more->next; + } + + if (count >= 2) + { + int i; + struct buffer_entry *e = bl->head, *f; + + ALLOC_OBJ_CLEAR(f, struct buffer_entry); + f->buf.data = malloc(size); + check_malloc_return(f->buf.data); + f->buf.capacity = size; + for (i = 0; e && i < count; ++i) + { + struct buffer_entry *next = e->next; + buf_copy(&f->buf, &e->buf); + buf_write(&f->buf, sep, sep_len); + free_buf(&e->buf); + free(e); + e = next; + } + bl->head = f; + f->next = more; + if (!more) + { + bl->tail = f; + } + } } } void -buffer_list_aggregate (struct buffer_list *bl, const size_t max) +buffer_list_aggregate(struct buffer_list *bl, const size_t max) { - buffer_list_aggregate_separator(bl, max, ""); + buffer_list_aggregate_separator(bl, max, ""); } void -buffer_list_pop (struct buffer_list *ol) +buffer_list_pop(struct buffer_list *ol) { - if (ol && ol->head) + if (ol && ol->head) { - struct buffer_entry *e = ol->head->next; - free_buf (&ol->head->buf); - free (ol->head); - ol->head = e; - --ol->size; - if (!e) - ol->tail = NULL; + struct buffer_entry *e = ol->head->next; + free_buf(&ol->head->buf); + free(ol->head); + ol->head = e; + --ol->size; + if (!e) + { + ol->tail = NULL; + } } } void -buffer_list_advance (struct buffer_list *ol, int n) +buffer_list_advance(struct buffer_list *ol, int n) { - if (ol->head) + if (ol->head) { - struct buffer *buf = &ol->head->buf; - ASSERT (buf_advance (buf, n)); - if (!BLEN (buf)) - buffer_list_pop (ol); + struct buffer *buf = &ol->head->buf; + ASSERT(buf_advance(buf, n)); + if (!BLEN(buf)) + { + buffer_list_pop(ol); + } } } struct buffer_list * -buffer_list_file (const char *fn, int max_line_len) +buffer_list_file(const char *fn, int max_line_len) { - FILE *fp = platform_fopen (fn, "r"); - struct buffer_list *bl = NULL; - - if (fp) - { - char *line = (char *) malloc (max_line_len); - if (line) - { - bl = buffer_list_new (0); - while (fgets (line, max_line_len, fp) != NULL) - buffer_list_push (bl, (unsigned char *)line); - free (line); - } - fclose (fp); - } - return bl; + FILE *fp = platform_fopen(fn, "r"); + struct buffer_list *bl = NULL; + + if (fp) + { + char *line = (char *) malloc(max_line_len); + if (line) + { + bl = buffer_list_new(0); + while (fgets(line, max_line_len, fp) != NULL) + buffer_list_push(bl, (unsigned char *)line); + free(line); + } + fclose(fp); + } + return bl; } |