OpenVPN
buffer.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "syshead.h"
29 
30 #include "common.h"
31 #include "buffer.h"
32 #include "error.h"
33 #include "mtu.h"
34 #include "misc.h"
35 
36 #include "memdbg.h"
37 
38 #include <wchar.h>
39 
40 size_t
41 array_mult_safe(const size_t m1, const size_t m2, const size_t extra)
42 {
43  const size_t limit = 0xFFFFFFFF;
44  unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra;
45  if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit))
46  {
47  msg(M_FATAL, "attempted allocation of excessively large array");
48  }
49  return (size_t) res;
50 }
51 
52 void
53 buf_size_error(const size_t size)
54 {
55  msg(M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
56 }
57 
58 struct buffer
59 #ifdef DMALLOC
60 alloc_buf_debug(size_t size, const char *file, int line)
61 #else
62 alloc_buf(size_t size)
63 #endif
64 {
65  struct buffer buf;
66 
67  if (!buf_size_valid(size))
68  {
69  buf_size_error(size);
70  }
71  buf.capacity = (int)size;
72  buf.offset = 0;
73  buf.len = 0;
74 #ifdef DMALLOC
75  buf.data = openvpn_dmalloc(file, line, size);
76 #else
77  buf.data = calloc(1, size);
78 #endif
80 
81  return buf;
82 }
83 
84 struct buffer
85 #ifdef DMALLOC
86 alloc_buf_gc_debug(size_t size, struct gc_arena *gc, const char *file, int line)
87 #else
88 alloc_buf_gc(size_t size, struct gc_arena *gc)
89 #endif
90 {
91  struct buffer buf;
92  if (!buf_size_valid(size))
93  {
94  buf_size_error(size);
95  }
96  buf.capacity = (int)size;
97  buf.offset = 0;
98  buf.len = 0;
99 #ifdef DMALLOC
100  buf.data = (uint8_t *) gc_malloc_debug(size, false, gc, file, line);
101 #else
102  buf.data = (uint8_t *) gc_malloc(size, false, gc);
103 #endif
104  if (size)
105  {
106  *buf.data = 0;
107  }
108  return buf;
109 }
110 
111 struct buffer
112 #ifdef DMALLOC
113 clone_buf_debug(const struct buffer *buf, const char *file, int line)
114 #else
115 clone_buf(const struct buffer *buf)
116 #endif
117 {
118  struct buffer ret;
119  ret.capacity = buf->capacity;
120  ret.offset = buf->offset;
121  ret.len = buf->len;
122 #ifdef DMALLOC
123  ret.data = (uint8_t *) openvpn_dmalloc(file, line, buf->capacity);
124 #else
125  ret.data = (uint8_t *) malloc(buf->capacity);
126 #endif
128  memcpy(BPTR(&ret), BPTR(buf), BLEN(buf));
129  return ret;
130 }
131 
132 #ifdef BUF_INIT_TRACKING
133 
134 bool
135 buf_init_debug(struct buffer *buf, int offset, const char *file, int line)
136 {
137  buf->debug_file = file;
138  buf->debug_line = line;
139  return buf_init_dowork(buf, offset);
140 }
141 
142 static inline int
143 buf_debug_line(const struct buffer *buf)
144 {
145  return buf->debug_line;
146 }
147 
148 static const char *
149 buf_debug_file(const struct buffer *buf)
150 {
151  return buf->debug_file;
152 }
153 
154 #else /* ifdef BUF_INIT_TRACKING */
155 
156 #define buf_debug_line(buf) 0
157 #define buf_debug_file(buf) "[UNDEF]"
158 
159 #endif /* ifdef BUF_INIT_TRACKING */
160 
161 void
162 buf_clear(struct buffer *buf)
163 {
164  if (buf->capacity > 0)
165  {
166  secure_memzero(buf->data, buf->capacity);
167  }
168  buf->len = 0;
169  buf->offset = 0;
170 }
171 
172 bool
173 buf_assign(struct buffer *dest, const struct buffer *src)
174 {
175  if (!buf_init(dest, src->offset))
176  {
177  return false;
178  }
179  return buf_write(dest, BPTR(src), BLEN(src));
180 }
181 
182 void
183 free_buf(struct buffer *buf)
184 {
185  free(buf->data);
186  CLEAR(*buf);
187 }
188 
189 static void
190 free_buf_gc(struct buffer *buf, struct gc_arena *gc)
191 {
192  if (gc)
193  {
194  struct gc_entry **e = &gc->list;
195 
196  while (*e)
197  {
198  /* check if this object is the one we want to delete */
199  if ((uint8_t *)(*e + 1) == buf->data)
200  {
201  struct gc_entry *to_delete = *e;
202 
203  /* remove element from linked list and free it */
204  *e = (*e)->next;
205  free(to_delete);
206 
207  break;
208  }
209 
210  e = &(*e)->next;
211  }
212  }
213 
214  CLEAR(*buf);
215 }
216 
217 /*
218  * Return a buffer for write that is a subset of another buffer
219  */
220 struct buffer
221 buf_sub(struct buffer *buf, int size, bool prepend)
222 {
223  struct buffer ret;
224  uint8_t *data;
225 
226  CLEAR(ret);
227  data = prepend ? buf_prepend(buf, size) : buf_write_alloc(buf, size);
228  if (data)
229  {
230  ret.capacity = size;
231  ret.data = data;
232  }
233  return ret;
234 }
235 
236 /*
237  * printf append to a buffer with overflow check
238  */
239 bool
240 buf_printf(struct buffer *buf, const char *format, ...)
241 {
242  int ret = false;
243  if (buf_defined(buf))
244  {
245  va_list arglist;
246  uint8_t *ptr = BEND(buf);
247  int cap = buf_forward_capacity(buf);
248 
249  if (cap > 0)
250  {
251  int stat;
252  va_start(arglist, format);
253  stat = vsnprintf((char *)ptr, cap, format, arglist);
254  va_end(arglist);
255  *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
256  buf->len += (int) strlen((char *)ptr);
257  if (stat >= 0 && stat < cap)
258  {
259  ret = true;
260  }
261  }
262  }
263  return ret;
264 }
265 
266 bool
267 buf_puts(struct buffer *buf, const char *str)
268 {
269  int ret = false;
270  uint8_t *ptr = BEND(buf);
271  int cap = buf_forward_capacity(buf);
272  if (cap > 0)
273  {
274  strncpynt((char *)ptr, str, cap);
275  *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
276  buf->len += (int) strlen((char *)ptr);
277  ret = true;
278  }
279  return ret;
280 }
281 
282 /*
283  * write a string to the end of a buffer that was
284  * truncated by buf_printf
285  */
286 void
287 buf_catrunc(struct buffer *buf, const char *str)
288 {
289  if (buf_forward_capacity(buf) <= 1)
290  {
291  size_t len = strlen(str) + 1;
292  if (len < buf_forward_capacity_total(buf))
293  {
294  memcpy(buf->data + buf->capacity - len, str, len);
295  }
296  }
297 }
298 
299 bool
300 buffer_write_file(const char *filename, const struct buffer *buf)
301 {
302  bool ret = false;
303  int fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY,
304  S_IRUSR | S_IWUSR);
305  if (fd == -1)
306  {
307  msg(M_ERRNO, "Cannot open file '%s' for write", filename);
308  return false;
309  }
310 
311  const ssize_t size = write(fd, BPTR(buf), BLEN(buf));
312  if (size != BLEN(buf))
313  {
314  msg(M_ERRNO, "Write error on file '%s'", filename);
315  goto cleanup;
316  }
317 
318  ret = true;
319 cleanup:
320  if (close(fd) < 0)
321  {
322  msg(M_ERRNO, "Close error on file %s", filename);
323  ret = false;
324  }
325  return ret;
326 }
327 
328 /*
329  * Garbage collection
330  */
331 
332 void *
333 #ifdef DMALLOC
334 gc_malloc_debug(size_t size, bool clear, struct gc_arena *a, const char *file, int line)
335 #else
336 gc_malloc(size_t size, bool clear, struct gc_arena *a)
337 #endif
338 {
339  void *ret;
340  if (a)
341  {
342  struct gc_entry *e;
343 #ifdef DMALLOC
344  e = (struct gc_entry *) openvpn_dmalloc(file, line, size + sizeof(struct gc_entry));
345 #else
346  e = (struct gc_entry *) malloc(size + sizeof(struct gc_entry));
347 #endif
349  ret = (char *) e + sizeof(struct gc_entry);
350  e->next = a->list;
351  a->list = e;
352  }
353  else
354  {
355 #ifdef DMALLOC
356  ret = openvpn_dmalloc(file, line, size);
357 #else
358  ret = malloc(size);
359 #endif
360  check_malloc_return(ret);
361  }
362 #ifndef ZERO_BUFFER_ON_ALLOC
363  if (clear)
364 #endif
365  memset(ret, 0, size);
366  return ret;
367 }
368 
369 void *
370 gc_realloc(void *ptr, size_t size, struct gc_arena *a)
371 {
372  void *ret = realloc(ptr, size);
373  check_malloc_return(ret);
374  if (a)
375  {
376  if (ptr && ptr != ret)
377  {
378  /* find the old entry and modify it if realloc changed
379  * the pointer */
380  struct gc_entry_special *e = NULL;
381  for (e = a->list_special; e != NULL; e = e->next)
382  {
383  if (e->addr == ptr)
384  {
385  break;
386  }
387  }
388  ASSERT(e);
389  ASSERT(e->addr == ptr);
390  e->addr = ret;
391  }
392  else if (!ptr)
393  {
394  /* sets e->addr to newptr */
395  gc_addspecial(ret, free, a);
396  }
397  }
398 
399  return ret;
400 }
401 
402 void
403 x_gc_free(struct gc_arena *a)
404 {
405  struct gc_entry *e;
406  e = a->list;
407  a->list = NULL;
408 
409  while (e != NULL)
410  {
411  struct gc_entry *next = e->next;
412  free(e);
413  e = next;
414  }
415 }
416 
417 /*
418  * Functions to handle special objects in gc_entries
419  */
420 
421 void
423 {
424  struct gc_entry_special *e;
425  e = a->list_special;
426  a->list_special = NULL;
427 
428  while (e != NULL)
429  {
430  struct gc_entry_special *next = e->next;
431  e->free_fnc(e->addr);
432  free(e);
433  e = next;
434  }
435 }
436 
437 void
438 gc_addspecial(void *addr, void (*free_function)(void *), struct gc_arena *a)
439 {
440  ASSERT(a);
441  struct gc_entry_special *e;
442 #ifdef DMALLOC
443  e = (struct gc_entry_special *) openvpn_dmalloc(file, line, sizeof(struct gc_entry_special));
444 #else
445  e = (struct gc_entry_special *) malloc(sizeof(struct gc_entry_special));
446 #endif
448  e->free_fnc = free_function;
449  e->addr = addr;
450 
451  e->next = a->list_special;
452  a->list_special = e;
453 }
454 
455 
456 /*
457  * Transfer src arena to dest, resetting src to an empty arena.
458  */
459 void
460 gc_transfer(struct gc_arena *dest, struct gc_arena *src)
461 {
462  if (dest && src)
463  {
464  struct gc_entry *e = src->list;
465  if (e)
466  {
467  while (e->next != NULL)
468  {
469  e = e->next;
470  }
471  e->next = dest->list;
472  dest->list = src->list;
473  src->list = NULL;
474  }
475  }
476 }
477 
478 /*
479  * Hex dump -- Output a binary buffer to a hex string and return it.
480  */
481 
482 char *
483 format_hex_ex(const uint8_t *data, int size, int maxoutput,
484  unsigned int space_break_flags, const char *separator,
485  struct gc_arena *gc)
486 {
487  const size_t bytes_per_hexblock = space_break_flags & FHE_SPACE_BREAK_MASK;
488  const size_t separator_len = separator ? strlen(separator) : 0;
489  static_assert(INT_MAX <= SIZE_MAX, "Code assumes INT_MAX <= SIZE_MAX");
490  const size_t out_len = maxoutput > 0 ? maxoutput :
491  ((size * 2) + ((size / bytes_per_hexblock) * separator_len) + 2);
492 
493  struct buffer out = alloc_buf_gc(out_len, gc);
494  for (int i = 0; i < size; ++i)
495  {
496  if (separator && i && !(i % bytes_per_hexblock))
497  {
498  buf_printf(&out, "%s", separator);
499  }
500  if (space_break_flags & FHE_CAPS)
501  {
502  buf_printf(&out, "%02X", data[i]);
503  }
504  else
505  {
506  buf_printf(&out, "%02x", data[i]);
507  }
508  }
509  buf_catrunc(&out, "[more...]");
510  return (char *)out.data;
511 }
512 
513 /*
514  * remove specific trailing character
515  */
516 
517 void
518 buf_rmtail(struct buffer *buf, uint8_t remove)
519 {
520  uint8_t *cp = BLAST(buf);
521  if (cp && *cp == remove)
522  {
523  *cp = '\0';
524  --buf->len;
525  }
526 }
527 
528 /*
529  * force a null termination even it requires
530  * truncation of the last char.
531  */
532 void
534 {
535  char *last = (char *) BLAST(buf);
536  if (last && *last == '\0') /* already terminated? */
537  {
538  return;
539  }
540 
541  if (!buf_safe(buf, 1)) /* make space for trailing null */
542  {
543  buf_inc_len(buf, -1);
544  }
545 
546  buf_write_u8(buf, 0);
547 }
548 
549 /*
550  * Remove trailing \r and \n chars and ensure
551  * null termination.
552  */
553 void
554 buf_chomp(struct buffer *buf)
555 {
556  while (true)
557  {
558  char *last = (char *) BLAST(buf);
559  if (!last)
560  {
561  break;
562  }
563  if (char_class(*last, CC_CRLF|CC_NULL))
564  {
565  if (!buf_inc_len(buf, -1))
566  {
567  break;
568  }
569  }
570  else
571  {
572  break;
573  }
574  }
575  buf_null_terminate(buf);
576 }
577 
578 const char *
579 skip_leading_whitespace(const char *str)
580 {
581  while (*str)
582  {
583  const char c = *str;
584  if (!(c == ' ' || c == '\t'))
585  {
586  break;
587  }
588  ++str;
589  }
590  return str;
591 }
592 
593 /*
594  * like buf_null_terminate, but operate on strings
595  */
596 void
597 string_null_terminate(char *str, int len, int capacity)
598 {
599  ASSERT(len >= 0 && len <= capacity && capacity > 0);
600  if (len < capacity)
601  {
602  *(str + len) = '\0';
603  }
604  else if (len == capacity)
605  {
606  *(str + len - 1) = '\0';
607  }
608 }
609 
610 /*
611  * Remove trailing \r and \n chars.
612  */
613 void
614 chomp(char *str)
615 {
616  rm_trailing_chars(str, "\r\n");
617 }
618 
619 /*
620  * Remove trailing chars
621  */
622 void
623 rm_trailing_chars(char *str, const char *what_to_delete)
624 {
625  bool modified;
626  do
627  {
628  const size_t len = strlen(str);
629  modified = false;
630  if (len > 0)
631  {
632  char *cp = str + (len - 1);
633  if (strchr(what_to_delete, *cp) != NULL)
634  {
635  *cp = '\0';
636  modified = true;
637  }
638  }
639  } while (modified);
640 }
641 
642 /*
643  * Allocate a string
644  */
645 char *
646 #ifdef DMALLOC
647 string_alloc_debug(const char *str, struct gc_arena *gc, const char *file, int line)
648 #else
649 string_alloc(const char *str, struct gc_arena *gc)
650 #endif
651 {
652  if (str)
653  {
654  const size_t n = strlen(str) + 1;
655  char *ret;
656 
657  if (gc)
658  {
659 #ifdef DMALLOC
660  ret = (char *) gc_malloc_debug(n, false, gc, file, line);
661 #else
662  ret = (char *) gc_malloc(n, false, gc);
663 #endif
664  }
665  else
666  {
667  /* If there are no garbage collector available, it's expected
668  * that the caller cleans up afterwards. This is coherent with the
669  * earlier behaviour when gc_malloc() would be called with gc == NULL
670  */
671 #ifdef DMALLOC
672  ret = openvpn_dmalloc(file, line, n);
673 #else
674  ret = calloc(1, n);
675 #endif
676  check_malloc_return(ret);
677  }
678  memcpy(ret, str, n);
679  return ret;
680  }
681  else
682  {
683  return NULL;
684  }
685 }
686 
687 /*
688  * Erase all characters in a string
689  */
690 void
691 string_clear(char *str)
692 {
693  if (str)
694  {
695  secure_memzero(str, strlen(str));
696  }
697 }
698 
699 /*
700  * Return the length of a string array
701  */
702 int
703 string_array_len(const char **array)
704 {
705  int i = 0;
706  if (array)
707  {
708  while (array[i])
709  {
710  ++i;
711  }
712  }
713  return i;
714 }
715 
716 char *
717 print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
718 {
719  struct buffer out = alloc_buf_gc(256, gc);
720  int i = 0;
721  for (;; )
722  {
723  const char *cp = *p++;
724  if (!cp)
725  {
726  break;
727  }
728  if (i)
729  {
730  buf_printf(&out, " ");
731  }
732  if (flags & PA_BRACKET)
733  {
734  buf_printf(&out, "[%s]", cp);
735  }
736  else
737  {
738  buf_printf(&out, "%s", cp);
739  }
740  ++i;
741  }
742  return BSTR(&out);
743 }
744 
745 /*
746  * Allocate a string inside a buffer
747  */
748 struct buffer
749 #ifdef DMALLOC
750 string_alloc_buf_debug(const char *str, struct gc_arena *gc, const char *file, int line)
751 #else
752 string_alloc_buf(const char *str, struct gc_arena *gc)
753 #endif
754 {
755  struct buffer buf;
756 
757  ASSERT(str);
758 
759 #ifdef DMALLOC
760  buf_set_read(&buf, (uint8_t *) string_alloc_debug(str, gc, file, line), strlen(str) + 1);
761 #else
762  buf_set_read(&buf, (uint8_t *) string_alloc(str, gc), strlen(str) + 1);
763 #endif
764 
765  if (buf.len > 0) /* Don't count trailing '\0' as part of length */
766  {
767  --buf.len;
768  }
769 
770  return buf;
771 }
772 
773 /*
774  * String comparison
775  */
776 
777 bool
778 buf_string_match_head_str(const struct buffer *src, const char *match)
779 {
780  const size_t size = strlen(match);
781  if (size > src->len)
782  {
783  return false;
784  }
785  return memcmp(BPTR(src), match, size) == 0;
786 }
787 
788 bool
789 buf_string_compare_advance(struct buffer *src, const char *match)
790 {
791  if (buf_string_match_head_str(src, match))
792  {
793  buf_advance(src, (int)strlen(match));
794  return true;
795  }
796  else
797  {
798  return false;
799  }
800 }
801 
802 int
803 buf_substring_len(const struct buffer *buf, int delim)
804 {
805  int i = 0;
806  struct buffer tmp = *buf;
807  int c;
808 
809  while ((c = buf_read_u8(&tmp)) >= 0)
810  {
811  ++i;
812  if (c == delim)
813  {
814  return i;
815  }
816  }
817  return -1;
818 }
819 
820 /*
821  * String parsing
822  */
823 
824 bool
825 buf_parse(struct buffer *buf, const int delim, char *line, const int size)
826 {
827  bool eol = false;
828  int n = 0;
829  int c;
830 
831  ASSERT(size > 0);
832 
833  do
834  {
835  c = buf_read_u8(buf);
836  if (c < 0)
837  {
838  eol = true;
839  }
840  if (c <= 0 || c == delim)
841  {
842  c = 0;
843  }
844  if (n >= size)
845  {
846  break;
847  }
848  line[n++] = (char)c;
849  }
850  while (c);
851 
852  line[size-1] = '\0';
853  return !(eol && !strlen(line));
854 }
855 
856 /*
857  * Print a string which might be NULL
858  */
859 const char *
860 np(const char *str)
861 {
862  if (str)
863  {
864  return str;
865  }
866  else
867  {
868  return "[NULL]";
869  }
870 }
871 
872 /*
873  * Classify and mutate strings based on character types.
874  */
875 
876 bool
877 char_class(const unsigned char c, const unsigned int flags)
878 {
879  if (!flags)
880  {
881  return false;
882  }
883  if (flags & CC_ANY)
884  {
885  return true;
886  }
887 
888  if ((flags & CC_NULL) && c == '\0')
889  {
890  return true;
891  }
892 
893  if ((flags & CC_ALNUM) && isalnum(c))
894  {
895  return true;
896  }
897  if ((flags & CC_ALPHA) && isalpha(c))
898  {
899  return true;
900  }
901  if ((flags & CC_ASCII) && isascii(c))
902  {
903  return true;
904  }
905  if ((flags & CC_CNTRL) && iscntrl(c))
906  {
907  return true;
908  }
909  if ((flags & CC_DIGIT) && isdigit(c))
910  {
911  return true;
912  }
913  if ((flags & CC_PRINT) && (c >= 32 && c != 127)) /* allow ascii non-control and UTF-8, consider DEL to be a control */
914  {
915  return true;
916  }
917  if ((flags & CC_PUNCT) && ispunct(c))
918  {
919  return true;
920  }
921  if ((flags & CC_SPACE) && isspace(c))
922  {
923  return true;
924  }
925  if ((flags & CC_XDIGIT) && isxdigit(c))
926  {
927  return true;
928  }
929 
930  if ((flags & CC_BLANK) && (c == ' ' || c == '\t'))
931  {
932  return true;
933  }
934  if ((flags & CC_NEWLINE) && c == '\n')
935  {
936  return true;
937  }
938  if ((flags & CC_CR) && c == '\r')
939  {
940  return true;
941  }
942 
943  if ((flags & CC_BACKSLASH) && c == '\\')
944  {
945  return true;
946  }
947  if ((flags & CC_UNDERBAR) && c == '_')
948  {
949  return true;
950  }
951  if ((flags & CC_DASH) && c == '-')
952  {
953  return true;
954  }
955  if ((flags & CC_DOT) && c == '.')
956  {
957  return true;
958  }
959  if ((flags & CC_COMMA) && c == ',')
960  {
961  return true;
962  }
963  if ((flags & CC_COLON) && c == ':')
964  {
965  return true;
966  }
967  if ((flags & CC_SLASH) && c == '/')
968  {
969  return true;
970  }
971  if ((flags & CC_SINGLE_QUOTE) && c == '\'')
972  {
973  return true;
974  }
975  if ((flags & CC_DOUBLE_QUOTE) && c == '\"')
976  {
977  return true;
978  }
979  if ((flags & CC_REVERSE_QUOTE) && c == '`')
980  {
981  return true;
982  }
983  if ((flags & CC_AT) && c == '@')
984  {
985  return true;
986  }
987  if ((flags & CC_EQUAL) && c == '=')
988  {
989  return true;
990  }
991  if ((flags & CC_LESS_THAN) && c == '<')
992  {
993  return true;
994  }
995  if ((flags & CC_GREATER_THAN) && c == '>')
996  {
997  return true;
998  }
999  if ((flags & CC_PIPE) && c == '|')
1000  {
1001  return true;
1002  }
1003  if ((flags & CC_QUESTION_MARK) && c == '?')
1004  {
1005  return true;
1006  }
1007  if ((flags & CC_ASTERISK) && c == '*')
1008  {
1009  return true;
1010  }
1011 
1012  return false;
1013 }
1014 
1015 static inline bool
1016 char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
1017 {
1018  return char_class(c, inclusive) && !char_class(c, exclusive);
1019 }
1020 
1021 bool
1022 string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
1023 {
1024  char c;
1025  ASSERT(str);
1026  while ((c = *str++))
1027  {
1028  if (!char_inc_exc(c, inclusive, exclusive))
1029  {
1030  return false;
1031  }
1032  }
1033  return true;
1034 }
1035 
1036 /*
1037  * Modify string in place.
1038  * Guaranteed to not increase string length.
1039  */
1040 bool
1041 string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
1042 {
1043  const char *in = str;
1044  bool ret = true;
1045 
1046  ASSERT(str);
1047 
1048  while (true)
1049  {
1050  char c = *in++;
1051  if (c)
1052  {
1053  if (!char_inc_exc(c, inclusive, exclusive))
1054  {
1055  c = replace;
1056  ret = false;
1057  }
1058  if (c)
1059  {
1060  *str++ = c;
1061  }
1062  }
1063  else
1064  {
1065  *str = '\0';
1066  break;
1067  }
1068  }
1069  return ret;
1070 }
1071 
1072 bool
1073 string_check_buf(struct buffer *buf, const unsigned int inclusive, const unsigned int exclusive)
1074 {
1075  ASSERT(buf);
1076 
1077  for (int i = 0; i < BLEN(buf); i++)
1078  {
1079  char c = BSTR(buf)[i];
1080 
1081  if (!char_inc_exc(c, inclusive, exclusive))
1082  {
1083  return false;
1084  }
1085  }
1086  return true;
1087 }
1088 
1089 const char *
1090 string_mod_const(const char *str,
1091  const unsigned int inclusive,
1092  const unsigned int exclusive,
1093  const char replace,
1094  struct gc_arena *gc)
1095 {
1096  if (str)
1097  {
1098  char *buf = string_alloc(str, gc);
1099  string_mod(buf, inclusive, exclusive, replace);
1100  return buf;
1101  }
1102  else
1103  {
1104  return NULL;
1105  }
1106 }
1107 
1108 void
1109 string_replace_leading(char *str, const char match, const char replace)
1110 {
1111  ASSERT(match != '\0');
1112  while (*str)
1113  {
1114  if (*str == match)
1115  {
1116  *str = replace;
1117  }
1118  else
1119  {
1120  break;
1121  }
1122  ++str;
1123  }
1124 }
1125 
1126 #ifdef VERIFY_ALIGNMENT
1127 void
1128 valign4(const struct buffer *buf, const char *file, const int line)
1129 {
1130  if (buf && buf->len)
1131  {
1132  int msglevel = D_ALIGN_DEBUG;
1133  const unsigned int u = (unsigned int) BPTR(buf);
1134 
1135  if (u & (PAYLOAD_ALIGN-1))
1136  {
1137  msglevel = D_ALIGN_ERRORS;
1138  }
1139 
1140  msg(msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d",
1141  (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "",
1142  file,
1143  line,
1144  (ptr_type)buf->data,
1145  buf->offset,
1146  buf->len,
1147  buf->capacity,
1148  buf_debug_file(buf),
1149  buf_debug_line(buf));
1150  }
1151 }
1152 #endif /* ifdef VERIFY_ALIGNMENT */
1153 
1154 /*
1155  * struct buffer_list
1156  */
1157 struct buffer_list *
1159 {
1160  struct buffer_list *ret;
1161  ALLOC_OBJ_CLEAR(ret, struct buffer_list);
1162  ret->size = 0;
1163  return ret;
1164 }
1165 
1166 void
1168 {
1169  if (ol)
1170  {
1171  buffer_list_reset(ol);
1172  free(ol);
1173  }
1174 }
1175 
1176 bool
1178 {
1179  return ol && ol->head != NULL;
1180 }
1181 
1182 void
1184 {
1185  struct buffer_entry *e = ol->head;
1186  while (e)
1187  {
1188  struct buffer_entry *next = e->next;
1189  free_buf(&e->buf);
1190  free(e);
1191  e = next;
1192  }
1193  ol->head = ol->tail = NULL;
1194  ol->size = 0;
1195 }
1196 
1197 void
1198 buffer_list_push(struct buffer_list *ol, const char *str)
1199 {
1200  if (str)
1201  {
1202  const size_t len = strlen((const char *)str);
1203  struct buffer_entry *e = buffer_list_push_data(ol, str, len+1);
1204  if (e)
1205  {
1206  e->buf.len = (int)len; /* Don't count trailing '\0' as part of length */
1207  }
1208  }
1209 }
1210 
1211 struct buffer_entry *
1212 buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
1213 {
1214  struct buffer_entry *e = NULL;
1215  if (data)
1216  {
1217  ALLOC_OBJ_CLEAR(e, struct buffer_entry);
1218 
1219  ++ol->size;
1220  if (ol->tail)
1221  {
1222  ASSERT(ol->head);
1223  ol->tail->next = e;
1224  }
1225  else
1226  {
1227  ASSERT(!ol->head);
1228  ol->head = e;
1229  }
1230  e->buf = alloc_buf(size);
1231  memcpy(e->buf.data, data, size);
1232  e->buf.len = (int)size;
1233  ol->tail = e;
1234  }
1235  return e;
1236 }
1237 
1238 struct buffer *
1240 {
1241  if (ol && ol->head)
1242  {
1243  return &ol->head->buf;
1244  }
1245  else
1246  {
1247  return NULL;
1248  }
1249 }
1250 
1251 void
1252 buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len,
1253  const char *sep)
1254 {
1255  const size_t sep_len = strlen(sep);
1256  struct buffer_entry *more = bl->head;
1257  size_t size = 0;
1258  int count = 0;
1259  for (count = 0; more; ++count)
1260  {
1261  size_t extra_len = BLEN(&more->buf) + sep_len;
1262  if (size + extra_len > max_len)
1263  {
1264  break;
1265  }
1266 
1267  size += extra_len;
1268  more = more->next;
1269  }
1270 
1271  if (count >= 2)
1272  {
1273  struct buffer_entry *f;
1274  ALLOC_OBJ_CLEAR(f, struct buffer_entry);
1275  f->buf = alloc_buf(size + 1); /* prevent 0-byte malloc */
1276 
1277  struct buffer_entry *e = bl->head;
1278  for (size_t i = 0; e && i < count; ++i)
1279  {
1280  struct buffer_entry *next = e->next;
1281  buf_copy(&f->buf, &e->buf);
1282  buf_write(&f->buf, sep, sep_len);
1283  free_buf(&e->buf);
1284  free(e);
1285  e = next;
1286  }
1287  bl->head = f;
1288  bl->size -= count - 1;
1289  f->next = more;
1290  if (!more)
1291  {
1292  bl->tail = f;
1293  }
1294  }
1295 }
1296 
1297 void
1298 buffer_list_aggregate(struct buffer_list *bl, const size_t max)
1299 {
1300  buffer_list_aggregate_separator(bl, max, "");
1301 }
1302 
1303 void
1305 {
1306  if (ol && ol->head)
1307  {
1308  struct buffer_entry *e = ol->head->next;
1309  free_buf(&ol->head->buf);
1310  free(ol->head);
1311  ol->head = e;
1312  --ol->size;
1313  if (!e)
1314  {
1315  ol->tail = NULL;
1316  }
1317  }
1318 }
1319 
1320 void
1322 {
1323  if (ol->head)
1324  {
1325  struct buffer *buf = &ol->head->buf;
1326  ASSERT(buf_advance(buf, n));
1327  if (!BLEN(buf))
1328  {
1329  buffer_list_pop(ol);
1330  }
1331  }
1332 }
1333 
1334 struct buffer_list *
1335 buffer_list_file(const char *fn, int max_line_len)
1336 {
1337  FILE *fp = platform_fopen(fn, "r");
1338  struct buffer_list *bl = NULL;
1339 
1340  if (fp)
1341  {
1342  char *line = (char *) malloc(max_line_len);
1343  if (line)
1344  {
1345  bl = buffer_list_new();
1346  while (fgets(line, max_line_len, fp) != NULL)
1347  {
1348  buffer_list_push(bl, line);
1349  }
1350  free(line);
1351  }
1352  fclose(fp);
1353  }
1354  return bl;
1355 }
1356 
1357 struct buffer
1358 buffer_read_from_file(const char *filename, struct gc_arena *gc)
1359 {
1360  struct buffer ret = { 0 };
1361 
1362  platform_stat_t file_stat = { 0 };
1363  if (platform_stat(filename, &file_stat) < 0)
1364  {
1365  return ret;
1366  }
1367 
1368  FILE *fp = platform_fopen(filename, "r");
1369  if (!fp)
1370  {
1371  return ret;
1372  }
1373 
1374  const size_t size = file_stat.st_size;
1375  ret = alloc_buf_gc(size + 1, gc); /* space for trailing \0 */
1376  size_t read_size = fread(BPTR(&ret), 1, size, fp);
1377  if (read_size == 0)
1378  {
1379  free_buf_gc(&ret, gc);
1380  goto cleanup;
1381  }
1382  ASSERT(buf_inc_len(&ret, (int)read_size));
1383  buf_null_terminate(&ret);
1384 
1385 cleanup:
1386  fclose(fp);
1387  return ret;
1388 }
PA_BRACKET
#define PA_BRACKET
Definition: buffer.h:144
gc_arena::list
struct gc_entry * list
First element of the linked list of gc_entry structures.
Definition: buffer.h:118
buf_safe
static bool buf_safe(const struct buffer *buf, size_t len)
Definition: buffer.h:520
buffer_write_file
bool buffer_write_file(const char *filename, const struct buffer *buf)
Write buffer contents to file.
Definition: buffer.c:300
buffer_read_from_file
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
Definition: buffer.c:1358
CC_BACKSLASH
#define CC_BACKSLASH
backslash
Definition: buffer.h:900
buf_rmtail
void buf_rmtail(struct buffer *buf, uint8_t remove)
Definition: buffer.c:518
error.h
gc_addspecial
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
Definition: buffer.c:438
string_array_len
int string_array_len(const char **array)
Definition: buffer.c:703
M_ERRNO
#define M_ERRNO
Definition: error.h:94
buf_forward_capacity_total
static int buf_forward_capacity_total(const struct buffer *buf)
Definition: buffer.h:559
CC_SLASH
#define CC_SLASH
slash
Definition: buffer.h:906
buffer::len
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
M_FATAL
#define M_FATAL
Definition: error.h:89
BLAST
#define BLAST(buf)
Definition: buffer.h:126
unlikely
#define unlikely(x)
Definition: syshead.h:36
gc_entry::next
struct gc_entry * next
Pointer to the next item in the linked list.
Definition: buffer.h:89
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:209
CC_UNDERBAR
#define CC_UNDERBAR
underscore
Definition: buffer.h:901
static_assert
#define static_assert(expr, diagnostic)
Definition: error.h:212
BSTR
#define BSTR(buf)
Definition: buffer.h:129
buf_size_valid
static bool buf_size_valid(const size_t size)
Definition: buffer.h:285
CC_ASTERISK
#define CC_ASTERISK
asterisk
Definition: buffer.h:916
rm_trailing_chars
void rm_trailing_chars(char *str, const char *what_to_delete)
Definition: buffer.c:623
array_mult_safe
size_t array_mult_safe(const size_t m1, const size_t m2, const size_t extra)
Definition: buffer.c:41
buffer::capacity
int capacity
Size in bytes of memory allocated by malloc().
Definition: buffer.h:62
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
buf_null_terminate
void buf_null_terminate(struct buffer *buf)
Definition: buffer.c:533
CC_CRLF
#define CC_CRLF
carriage return or newline
Definition: buffer.h:920
CC_DASH
#define CC_DASH
dash
Definition: buffer.h:902
gc_entry
Garbage collection entry for one dynamically allocated block of memory.
Definition: buffer.h:87
buffer_list_peek
struct buffer * buffer_list_peek(struct buffer_list *ol)
Retrieve the head buffer.
Definition: buffer.c:1239
buffer_list_aggregate_separator
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 .
Definition: buffer.c:1252
buf_sub
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition: buffer.c:221
buf_clear
void buf_clear(struct buffer *buf)
Definition: buffer.c:162
buf_copy
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Definition: buffer.h:712
format_hex_ex
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition: buffer.c:483
BEND
#define BEND(buf)
Definition: buffer.h:125
clone_buf
struct buffer clone_buf(const struct buffer *buf)
Definition: buffer.c:115
CC_COLON
#define CC_COLON
colon
Definition: buffer.h:905
gc_entry_special::free_fnc
void(* free_fnc)(void *)
Definition: buffer.h:101
gc_arena::list_special
struct gc_entry_special * list_special
Definition: buffer.h:120
CC_ALNUM
#define CC_ALNUM
alphanumeric isalnum()
Definition: buffer.h:886
D_ALIGN_DEBUG
#define D_ALIGN_DEBUG
Definition: errlevel.h:142
buffer_list_push_data
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.
Definition: buffer.c:1212
x_gc_freespecial
void x_gc_freespecial(struct gc_arena *a)
Definition: buffer.c:422
CLEAR
#define CLEAR(x)
Definition: basic.h:33
CC_NEWLINE
#define CC_NEWLINE
newline
Definition: buffer.h:897
mtu.h
buffer_list_file
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
Definition: buffer.c:1335
CC_DOUBLE_QUOTE
#define CC_DOUBLE_QUOTE
double quote
Definition: buffer.h:908
platform_stat_t
struct _stat platform_stat_t
Definition: platform.h:142
string_alloc
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:649
secure_memzero
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition: buffer.h:414
ASSERT
#define ASSERT(x)
Definition: error.h:195
string_clear
void string_clear(char *str)
Definition: buffer.c:691
string_replace_leading
void string_replace_leading(char *str, const char match, const char replace)
Definition: buffer.c:1109
buffer_entry::buf
struct buffer buf
Definition: buffer.h:1116
buf_chomp
void buf_chomp(struct buffer *buf)
Definition: buffer.c:554
buf_advance
static bool buf_advance(struct buffer *buf, int size)
Definition: buffer.h:618
buf_size_error
void buf_size_error(const size_t size)
Definition: buffer.c:53
buf_inc_len
static bool buf_inc_len(struct buffer *buf, int inc)
Definition: buffer.h:590
CC_QUESTION_MARK
#define CC_QUESTION_MARK
question mark
Definition: buffer.h:915
CC_SINGLE_QUOTE
#define CC_SINGLE_QUOTE
single quote
Definition: buffer.h:907
write
@ write
Definition: interactive.c:224
BLEN
#define BLEN(buf)
Definition: buffer.h:127
buf_debug_file
#define buf_debug_file(buf)
Definition: buffer.c:157
buf_write_u8
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition: buffer.h:692
buf_assign
bool buf_assign(struct buffer *dest, const struct buffer *src)
Definition: buffer.c:173
CC_PRINT
#define CC_PRINT
printable (>= 32, != 127)
Definition: buffer.h:891
string_mod
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...
Definition: buffer.c:1041
buffer_entry::next
struct buffer_entry * next
Definition: buffer.h:1117
misc.h
buffer_list_push
void buffer_list_push(struct buffer_list *ol, const char *str)
Allocates and appends a new buffer containing str as data to ol.
Definition: buffer.c:1198
CC_LESS_THAN
#define CC_LESS_THAN
less than sign
Definition: buffer.h:912
FHE_CAPS
#define FHE_CAPS
Definition: buffer.h:498
CC_GREATER_THAN
#define CC_GREATER_THAN
greater than sign
Definition: buffer.h:913
CC_CR
#define CC_CR
carriage return
Definition: buffer.h:898
char_class
bool char_class(const unsigned char c, const unsigned int flags)
Definition: buffer.c:877
CC_PIPE
#define CC_PIPE
pipe
Definition: buffer.h:914
CC_EQUAL
#define CC_EQUAL
equal sign
Definition: buffer.h:911
gc_transfer
void gc_transfer(struct gc_arena *dest, struct gc_arena *src)
Definition: buffer.c:460
CC_REVERSE_QUOTE
#define CC_REVERSE_QUOTE
reverse quote
Definition: buffer.h:909
string_check_buf
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.
Definition: buffer.c:1073
CC_DIGIT
#define CC_DIGIT
digit isdigit()
Definition: buffer.h:890
CC_BLANK
#define CC_BLANK
space or tab
Definition: buffer.h:896
CC_AT
#define CC_AT
at sign
Definition: buffer.h:910
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
buffer_list::size
int size
Definition: buffer.h:1124
buffer_list_new
struct buffer_list * buffer_list_new(void)
Allocate an empty buffer list of capacity max_size.
Definition: buffer.c:1158
CC_SPACE
#define CC_SPACE
whitespace isspace()
Definition: buffer.h:893
CC_ASCII
#define CC_ASCII
ASCII character.
Definition: buffer.h:888
CC_COMMA
#define CC_COMMA
comma
Definition: buffer.h:904
buf_write
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:668
CC_ANY
#define CC_ANY
any character
Definition: buffer.h:883
buffer.h
syshead.h
platform_fopen
FILE * platform_fopen(const char *path, const char *mode)
Definition: platform.c:501
BPTR
#define BPTR(buf)
Definition: buffer.h:124
CC_DOT
#define CC_DOT
dot
Definition: buffer.h:903
np
const char * np(const char *str)
Definition: buffer.c:860
CC_ALPHA
#define CC_ALPHA
alphabetic isalpha()
Definition: buffer.h:887
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
free_buf_gc
static void free_buf_gc(struct buffer *buf, struct gc_arena *gc)
Definition: buffer.c:190
string_class
bool string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1022
CC_PUNCT
#define CC_PUNCT
punctuation ispunct()
Definition: buffer.h:892
buffer::offset
int offset
Offset in bytes of the actual content within the allocated memory.
Definition: buffer.h:64
strncpynt
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition: buffer.h:361
buf_init_dowork
static bool buf_init_dowork(struct buffer *buf, int offset)
Definition: buffer.h:319
buf_prepend
static uint8_t * buf_prepend(struct buffer *buf, int size)
Definition: buffer.h:606
buffer_list::tail
struct buffer_entry * tail
Definition: buffer.h:1123
buffer_list_pop
void buffer_list_pop(struct buffer_list *ol)
Definition: buffer.c:1304
gc_entry_special
Garbage collection entry for a specially allocated structure that needs a custom free function to be ...
Definition: buffer.h:98
platform_stat
int platform_stat(const char *path, platform_stat_t *buf)
Definition: platform.c:527
buf_puts
bool buf_puts(struct buffer *buf, const char *str)
Definition: buffer.c:267
free_buf
void free_buf(struct buffer *buf)
Definition: buffer.c:183
common.h
string_null_terminate
void string_null_terminate(char *str, int len, int capacity)
Definition: buffer.c:597
buf_string_match_head_str
bool buf_string_match_head_str(const struct buffer *src, const char *match)
Definition: buffer.c:778
chomp
void chomp(char *str)
Definition: buffer.c:614
PAYLOAD_ALIGN
#define PAYLOAD_ALIGN
Definition: mtu.h:91
FHE_SPACE_BREAK_MASK
#define FHE_SPACE_BREAK_MASK
Definition: buffer.h:497
buf_string_compare_advance
bool buf_string_compare_advance(struct buffer *src, const char *match)
Definition: buffer.c:789
buffer_list_advance
void buffer_list_advance(struct buffer_list *ol, int n)
Definition: buffer.c:1321
gc_malloc
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:336
ptr_type
unsigned long ptr_type
Definition: common.h:58
x_gc_free
void x_gc_free(struct gc_arena *a)
Definition: buffer.c:403
string_alloc_buf
struct buffer string_alloc_buf(const char *str, struct gc_arena *gc)
Definition: buffer.c:752
buffer_list_defined
bool buffer_list_defined(const struct buffer_list *ol)
Checks if the list is valid and non-empty.
Definition: buffer.c:1177
ALLOC_OBJ_CLEAR
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1060
gc_entry_special::next
struct gc_entry_special * next
Definition: buffer.h:100
buf_write_alloc
static uint8_t * buf_write_alloc(struct buffer *buf, size_t size)
Definition: buffer.h:635
config.h
D_ALIGN_ERRORS
#define D_ALIGN_ERRORS
Definition: errlevel.h:70
buffer_list_free
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
Definition: buffer.c:1167
buffer_list_aggregate
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 .
Definition: buffer.c:1298
gc_entry_special::addr
void * addr
Definition: buffer.h:102
CC_NULL
#define CC_NULL
null character \0
Definition: buffer.h:884
CC_XDIGIT
#define CC_XDIGIT
hex digit isxdigit()
Definition: buffer.h:894
check_malloc_return
static void check_malloc_return(void *p)
Definition: buffer.h:1103
buf_debug_line
#define buf_debug_line(buf)
Definition: buffer.c:156
buf_substring_len
int buf_substring_len(const struct buffer *buf, int delim)
Definition: buffer.c:803
buf_read_u8
static int buf_read_u8(struct buffer *buf)
Definition: buffer.h:790
platform_open
int platform_open(const char *path, int flags, int mode)
Definition: platform.c:514
buf_forward_capacity
static int buf_forward_capacity(const struct buffer *buf)
Definition: buffer.h:541
print_argv
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Definition: buffer.c:717
CC_CNTRL
#define CC_CNTRL
control character iscntrl()
Definition: buffer.h:889
char_inc_exc
static bool char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1016
alloc_buf
struct buffer alloc_buf(size_t size)
Definition: buffer.c:62
memdbg.h
buffer_list_reset
void buffer_list_reset(struct buffer_list *ol)
Empty the list ol and frees all the contained buffers.
Definition: buffer.c:1183
skip_leading_whitespace
const char * skip_leading_whitespace(const char *str)
Definition: buffer.c:579
buffer_list
Definition: buffer.h:1120
string_mod_const
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...
Definition: buffer.c:1090
msg
#define msg(flags,...)
Definition: error.h:144
gc_realloc
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
Definition: buffer.c:370
buffer_entry
Definition: buffer.h:1114
buf_defined
static bool buf_defined(const struct buffer *buf)
Definition: buffer.h:228
http-client.f
string f
Definition: http-client.py:6
buf_printf
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:240
ptr_format
#define ptr_format
Definition: common.h:49
buffer_list::head
struct buffer_entry * head
Definition: buffer.h:1122
buf_set_read
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Definition: buffer.h:348
gc
struct gc_arena gc
Definition: test_ssl.c:155
buffer::data
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
buf_catrunc
void buf_catrunc(struct buffer *buf, const char *str)
Definition: buffer.c:287
buf_parse
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition: buffer.c:825
cleanup
static int cleanup(void **state)
Definition: test_pkcs11.c:290