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-2023 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 /*
284  * This is necessary due to certain buggy implementations of snprintf,
285  * that don't guarantee null termination for size > 0.
286  *
287  * Return false on overflow.
288  *
289  * This functionality is duplicated in src/openvpnserv/common.c
290  * Any modifications here should be done to the other place as well.
291  */
292 
293 bool
294 openvpn_snprintf(char *str, size_t size, const char *format, ...)
295 {
296  va_list arglist;
297  int len = -1;
298  if (size > 0)
299  {
300  va_start(arglist, format);
301  len = vsnprintf(str, size, format, arglist);
302  va_end(arglist);
303  str[size - 1] = 0;
304  }
305  return (len >= 0 && len < size);
306 }
307 
308 /*
309  * write a string to the end of a buffer that was
310  * truncated by buf_printf
311  */
312 void
313 buf_catrunc(struct buffer *buf, const char *str)
314 {
315  if (buf_forward_capacity(buf) <= 1)
316  {
317  size_t len = strlen(str) + 1;
318  if (len < buf_forward_capacity_total(buf))
319  {
320  memcpy(buf->data + buf->capacity - len, str, len);
321  }
322  }
323 }
324 
325 /*
326  * convert a multi-line output to one line
327  */
328 void
330 {
331  uint8_t *cp = BPTR(buf);
332  int len = BLEN(buf);
333  while (len--)
334  {
335  if (*cp == '\n')
336  {
337  *cp = '|';
338  }
339  ++cp;
340  }
341 }
342 
343 bool
344 buffer_write_file(const char *filename, const struct buffer *buf)
345 {
346  bool ret = false;
347  int fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY,
348  S_IRUSR | S_IWUSR);
349  if (fd == -1)
350  {
351  msg(M_ERRNO, "Cannot open file '%s' for write", filename);
352  return false;
353  }
354 
355  const int size = write(fd, BPTR(buf), BLEN(buf));
356  if (size != BLEN(buf))
357  {
358  msg(M_ERRNO, "Write error on file '%s'", filename);
359  goto cleanup;
360  }
361 
362  ret = true;
363 cleanup:
364  if (close(fd) < 0)
365  {
366  msg(M_ERRNO, "Close error on file %s", filename);
367  ret = false;
368  }
369  return ret;
370 }
371 
372 /*
373  * Garbage collection
374  */
375 
376 void *
377 #ifdef DMALLOC
378 gc_malloc_debug(size_t size, bool clear, struct gc_arena *a, const char *file, int line)
379 #else
380 gc_malloc(size_t size, bool clear, struct gc_arena *a)
381 #endif
382 {
383  void *ret;
384  if (a)
385  {
386  struct gc_entry *e;
387 #ifdef DMALLOC
388  e = (struct gc_entry *) openvpn_dmalloc(file, line, size + sizeof(struct gc_entry));
389 #else
390  e = (struct gc_entry *) malloc(size + sizeof(struct gc_entry));
391 #endif
393  ret = (char *) e + sizeof(struct gc_entry);
394  e->next = a->list;
395  a->list = e;
396  }
397  else
398  {
399 #ifdef DMALLOC
400  ret = openvpn_dmalloc(file, line, size);
401 #else
402  ret = malloc(size);
403 #endif
404  check_malloc_return(ret);
405  }
406 #ifndef ZERO_BUFFER_ON_ALLOC
407  if (clear)
408 #endif
409  memset(ret, 0, size);
410  return ret;
411 }
412 
413 void *
414 gc_realloc(void *ptr, size_t size, struct gc_arena *a)
415 {
416  void *ret = realloc(ptr, size);
417  check_malloc_return(ret);
418  if (a)
419  {
420  if (ptr && ptr != ret)
421  {
422  /* find the old entry and modify it if realloc changed
423  * the pointer */
424  struct gc_entry_special *e = NULL;
425  for (e = a->list_special; e != NULL; e = e->next)
426  {
427  if (e->addr == ptr)
428  {
429  break;
430  }
431  }
432  ASSERT(e);
433  ASSERT(e->addr == ptr);
434  e->addr = ret;
435  }
436  else if (!ptr)
437  {
438  /* sets e->addr to newptr */
439  gc_addspecial(ret, free, a);
440  }
441  }
442 
443  return ret;
444 }
445 
446 void
447 x_gc_free(struct gc_arena *a)
448 {
449  struct gc_entry *e;
450  e = a->list;
451  a->list = NULL;
452 
453  while (e != NULL)
454  {
455  struct gc_entry *next = e->next;
456  free(e);
457  e = next;
458  }
459 }
460 
461 /*
462  * Functions to handle special objects in gc_entries
463  */
464 
465 void
467 {
468  struct gc_entry_special *e;
469  e = a->list_special;
470  a->list_special = NULL;
471 
472  while (e != NULL)
473  {
474  struct gc_entry_special *next = e->next;
475  e->free_fnc(e->addr);
476  free(e);
477  e = next;
478  }
479 }
480 
481 void
482 gc_addspecial(void *addr, void (*free_function)(void *), struct gc_arena *a)
483 {
484  ASSERT(a);
485  struct gc_entry_special *e;
486 #ifdef DMALLOC
487  e = (struct gc_entry_special *) openvpn_dmalloc(file, line, sizeof(struct gc_entry_special));
488 #else
489  e = (struct gc_entry_special *) malloc(sizeof(struct gc_entry_special));
490 #endif
492  e->free_fnc = free_function;
493  e->addr = addr;
494 
495  e->next = a->list_special;
496  a->list_special = e;
497 }
498 
499 
500 /*
501  * Transfer src arena to dest, resetting src to an empty arena.
502  */
503 void
504 gc_transfer(struct gc_arena *dest, struct gc_arena *src)
505 {
506  if (dest && src)
507  {
508  struct gc_entry *e = src->list;
509  if (e)
510  {
511  while (e->next != NULL)
512  {
513  e = e->next;
514  }
515  e->next = dest->list;
516  dest->list = src->list;
517  src->list = NULL;
518  }
519  }
520 }
521 
522 /*
523  * Hex dump -- Output a binary buffer to a hex string and return it.
524  */
525 
526 char *
527 format_hex_ex(const uint8_t *data, int size, int maxoutput,
528  unsigned int space_break_flags, const char *separator,
529  struct gc_arena *gc)
530 {
531  const size_t bytes_per_hexblock = space_break_flags & FHE_SPACE_BREAK_MASK;
532  const size_t separator_len = separator ? strlen(separator) : 0;
533  static_assert(INT_MAX <= SIZE_MAX, "Code assumes INT_MAX <= SIZE_MAX");
534  const size_t out_len = maxoutput > 0 ? maxoutput :
535  ((size * 2) + ((size / bytes_per_hexblock) * separator_len) + 2);
536 
537  struct buffer out = alloc_buf_gc(out_len, gc);
538  for (int i = 0; i < size; ++i)
539  {
540  if (separator && i && !(i % bytes_per_hexblock))
541  {
542  buf_printf(&out, "%s", separator);
543  }
544  if (space_break_flags & FHE_CAPS)
545  {
546  buf_printf(&out, "%02X", data[i]);
547  }
548  else
549  {
550  buf_printf(&out, "%02x", data[i]);
551  }
552  }
553  buf_catrunc(&out, "[more...]");
554  return (char *)out.data;
555 }
556 
557 /*
558  * remove specific trailing character
559  */
560 
561 void
562 buf_rmtail(struct buffer *buf, uint8_t remove)
563 {
564  uint8_t *cp = BLAST(buf);
565  if (cp && *cp == remove)
566  {
567  *cp = '\0';
568  --buf->len;
569  }
570 }
571 
572 /*
573  * force a null termination even it requires
574  * truncation of the last char.
575  */
576 void
578 {
579  char *last = (char *) BLAST(buf);
580  if (last && *last == '\0') /* already terminated? */
581  {
582  return;
583  }
584 
585  if (!buf_safe(buf, 1)) /* make space for trailing null */
586  {
587  buf_inc_len(buf, -1);
588  }
589 
590  buf_write_u8(buf, 0);
591 }
592 
593 /*
594  * Remove trailing \r and \n chars and ensure
595  * null termination.
596  */
597 void
598 buf_chomp(struct buffer *buf)
599 {
600  while (true)
601  {
602  char *last = (char *) BLAST(buf);
603  if (!last)
604  {
605  break;
606  }
607  if (char_class(*last, CC_CRLF|CC_NULL))
608  {
609  if (!buf_inc_len(buf, -1))
610  {
611  break;
612  }
613  }
614  else
615  {
616  break;
617  }
618  }
619  buf_null_terminate(buf);
620 }
621 
622 const char *
623 skip_leading_whitespace(const char *str)
624 {
625  while (*str)
626  {
627  const char c = *str;
628  if (!(c == ' ' || c == '\t'))
629  {
630  break;
631  }
632  ++str;
633  }
634  return str;
635 }
636 
637 /*
638  * like buf_null_terminate, but operate on strings
639  */
640 void
641 string_null_terminate(char *str, int len, int capacity)
642 {
643  ASSERT(len >= 0 && len <= capacity && capacity > 0);
644  if (len < capacity)
645  {
646  *(str + len) = '\0';
647  }
648  else if (len == capacity)
649  {
650  *(str + len - 1) = '\0';
651  }
652 }
653 
654 /*
655  * Remove trailing \r and \n chars.
656  */
657 void
658 chomp(char *str)
659 {
660  rm_trailing_chars(str, "\r\n");
661 }
662 
663 /*
664  * Remove trailing chars
665  */
666 void
667 rm_trailing_chars(char *str, const char *what_to_delete)
668 {
669  bool modified;
670  do
671  {
672  const size_t len = strlen(str);
673  modified = false;
674  if (len > 0)
675  {
676  char *cp = str + (len - 1);
677  if (strchr(what_to_delete, *cp) != NULL)
678  {
679  *cp = '\0';
680  modified = true;
681  }
682  }
683  } while (modified);
684 }
685 
686 /*
687  * Allocate a string
688  */
689 char *
690 #ifdef DMALLOC
691 string_alloc_debug(const char *str, struct gc_arena *gc, const char *file, int line)
692 #else
693 string_alloc(const char *str, struct gc_arena *gc)
694 #endif
695 {
696  if (str)
697  {
698  const size_t n = strlen(str) + 1;
699  char *ret;
700 
701  if (gc)
702  {
703 #ifdef DMALLOC
704  ret = (char *) gc_malloc_debug(n, false, gc, file, line);
705 #else
706  ret = (char *) gc_malloc(n, false, gc);
707 #endif
708  }
709  else
710  {
711  /* If there are no garbage collector available, it's expected
712  * that the caller cleans up afterwards. This is coherent with the
713  * earlier behaviour when gc_malloc() would be called with gc == NULL
714  */
715 #ifdef DMALLOC
716  ret = openvpn_dmalloc(file, line, n);
717 #else
718  ret = calloc(1, n);
719 #endif
720  check_malloc_return(ret);
721  }
722  memcpy(ret, str, n);
723  return ret;
724  }
725  else
726  {
727  return NULL;
728  }
729 }
730 
731 /*
732  * Erase all characters in a string
733  */
734 void
735 string_clear(char *str)
736 {
737  if (str)
738  {
739  secure_memzero(str, strlen(str));
740  }
741 }
742 
743 /*
744  * Return the length of a string array
745  */
746 int
747 string_array_len(const char **array)
748 {
749  int i = 0;
750  if (array)
751  {
752  while (array[i])
753  {
754  ++i;
755  }
756  }
757  return i;
758 }
759 
760 char *
761 print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
762 {
763  struct buffer out = alloc_buf_gc(256, gc);
764  int i = 0;
765  for (;; )
766  {
767  const char *cp = *p++;
768  if (!cp)
769  {
770  break;
771  }
772  if (i)
773  {
774  buf_printf(&out, " ");
775  }
776  if (flags & PA_BRACKET)
777  {
778  buf_printf(&out, "[%s]", cp);
779  }
780  else
781  {
782  buf_printf(&out, "%s", cp);
783  }
784  ++i;
785  }
786  return BSTR(&out);
787 }
788 
789 /*
790  * Allocate a string inside a buffer
791  */
792 struct buffer
793 #ifdef DMALLOC
794 string_alloc_buf_debug(const char *str, struct gc_arena *gc, const char *file, int line)
795 #else
796 string_alloc_buf(const char *str, struct gc_arena *gc)
797 #endif
798 {
799  struct buffer buf;
800 
801  ASSERT(str);
802 
803 #ifdef DMALLOC
804  buf_set_read(&buf, (uint8_t *) string_alloc_debug(str, gc, file, line), strlen(str) + 1);
805 #else
806  buf_set_read(&buf, (uint8_t *) string_alloc(str, gc), strlen(str) + 1);
807 #endif
808 
809  if (buf.len > 0) /* Don't count trailing '\0' as part of length */
810  {
811  --buf.len;
812  }
813 
814  return buf;
815 }
816 
817 /*
818  * String comparison
819  */
820 
821 bool
822 buf_string_match_head_str(const struct buffer *src, const char *match)
823 {
824  const size_t size = strlen(match);
825  if (size > src->len)
826  {
827  return false;
828  }
829  return memcmp(BPTR(src), match, size) == 0;
830 }
831 
832 bool
833 buf_string_compare_advance(struct buffer *src, const char *match)
834 {
835  if (buf_string_match_head_str(src, match))
836  {
837  buf_advance(src, (int)strlen(match));
838  return true;
839  }
840  else
841  {
842  return false;
843  }
844 }
845 
846 int
847 buf_substring_len(const struct buffer *buf, int delim)
848 {
849  int i = 0;
850  struct buffer tmp = *buf;
851  int c;
852 
853  while ((c = buf_read_u8(&tmp)) >= 0)
854  {
855  ++i;
856  if (c == delim)
857  {
858  return i;
859  }
860  }
861  return -1;
862 }
863 
864 /*
865  * String parsing
866  */
867 
868 bool
869 buf_parse(struct buffer *buf, const int delim, char *line, const int size)
870 {
871  bool eol = false;
872  int n = 0;
873  int c;
874 
875  ASSERT(size > 0);
876 
877  do
878  {
879  c = buf_read_u8(buf);
880  if (c < 0)
881  {
882  eol = true;
883  }
884  if (c <= 0 || c == delim)
885  {
886  c = 0;
887  }
888  if (n >= size)
889  {
890  break;
891  }
892  line[n++] = c;
893  }
894  while (c);
895 
896  line[size-1] = '\0';
897  return !(eol && !strlen(line));
898 }
899 
900 /*
901  * Print a string which might be NULL
902  */
903 const char *
904 np(const char *str)
905 {
906  if (str)
907  {
908  return str;
909  }
910  else
911  {
912  return "[NULL]";
913  }
914 }
915 
916 /*
917  * Classify and mutate strings based on character types.
918  */
919 
920 bool
921 char_class(const unsigned char c, const unsigned int flags)
922 {
923  if (!flags)
924  {
925  return false;
926  }
927  if (flags & CC_ANY)
928  {
929  return true;
930  }
931 
932  if ((flags & CC_NULL) && c == '\0')
933  {
934  return true;
935  }
936 
937  if ((flags & CC_ALNUM) && isalnum(c))
938  {
939  return true;
940  }
941  if ((flags & CC_ALPHA) && isalpha(c))
942  {
943  return true;
944  }
945  if ((flags & CC_ASCII) && isascii(c))
946  {
947  return true;
948  }
949  if ((flags & CC_CNTRL) && iscntrl(c))
950  {
951  return true;
952  }
953  if ((flags & CC_DIGIT) && isdigit(c))
954  {
955  return true;
956  }
957  if ((flags & CC_PRINT) && (c >= 32 && c != 127)) /* allow ascii non-control and UTF-8, consider DEL to be a control */
958  {
959  return true;
960  }
961  if ((flags & CC_PUNCT) && ispunct(c))
962  {
963  return true;
964  }
965  if ((flags & CC_SPACE) && isspace(c))
966  {
967  return true;
968  }
969  if ((flags & CC_XDIGIT) && isxdigit(c))
970  {
971  return true;
972  }
973 
974  if ((flags & CC_BLANK) && (c == ' ' || c == '\t'))
975  {
976  return true;
977  }
978  if ((flags & CC_NEWLINE) && c == '\n')
979  {
980  return true;
981  }
982  if ((flags & CC_CR) && c == '\r')
983  {
984  return true;
985  }
986 
987  if ((flags & CC_BACKSLASH) && c == '\\')
988  {
989  return true;
990  }
991  if ((flags & CC_UNDERBAR) && c == '_')
992  {
993  return true;
994  }
995  if ((flags & CC_DASH) && c == '-')
996  {
997  return true;
998  }
999  if ((flags & CC_DOT) && c == '.')
1000  {
1001  return true;
1002  }
1003  if ((flags & CC_COMMA) && c == ',')
1004  {
1005  return true;
1006  }
1007  if ((flags & CC_COLON) && c == ':')
1008  {
1009  return true;
1010  }
1011  if ((flags & CC_SLASH) && c == '/')
1012  {
1013  return true;
1014  }
1015  if ((flags & CC_SINGLE_QUOTE) && c == '\'')
1016  {
1017  return true;
1018  }
1019  if ((flags & CC_DOUBLE_QUOTE) && c == '\"')
1020  {
1021  return true;
1022  }
1023  if ((flags & CC_REVERSE_QUOTE) && c == '`')
1024  {
1025  return true;
1026  }
1027  if ((flags & CC_AT) && c == '@')
1028  {
1029  return true;
1030  }
1031  if ((flags & CC_EQUAL) && c == '=')
1032  {
1033  return true;
1034  }
1035  if ((flags & CC_LESS_THAN) && c == '<')
1036  {
1037  return true;
1038  }
1039  if ((flags & CC_GREATER_THAN) && c == '>')
1040  {
1041  return true;
1042  }
1043  if ((flags & CC_PIPE) && c == '|')
1044  {
1045  return true;
1046  }
1047  if ((flags & CC_QUESTION_MARK) && c == '?')
1048  {
1049  return true;
1050  }
1051  if ((flags & CC_ASTERISK) && c == '*')
1052  {
1053  return true;
1054  }
1055 
1056  return false;
1057 }
1058 
1059 static inline bool
1060 char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
1061 {
1062  return char_class(c, inclusive) && !char_class(c, exclusive);
1063 }
1064 
1065 bool
1066 string_class(const char *str, const unsigned int inclusive, const unsigned int exclusive)
1067 {
1068  char c;
1069  ASSERT(str);
1070  while ((c = *str++))
1071  {
1072  if (!char_inc_exc(c, inclusive, exclusive))
1073  {
1074  return false;
1075  }
1076  }
1077  return true;
1078 }
1079 
1080 /*
1081  * Modify string in place.
1082  * Guaranteed to not increase string length.
1083  */
1084 bool
1085 string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
1086 {
1087  const char *in = str;
1088  bool ret = true;
1089 
1090  ASSERT(str);
1091 
1092  while (true)
1093  {
1094  char c = *in++;
1095  if (c)
1096  {
1097  if (!char_inc_exc(c, inclusive, exclusive))
1098  {
1099  c = replace;
1100  ret = false;
1101  }
1102  if (c)
1103  {
1104  *str++ = c;
1105  }
1106  }
1107  else
1108  {
1109  *str = '\0';
1110  break;
1111  }
1112  }
1113  return ret;
1114 }
1115 
1116 const char *
1117 string_mod_const(const char *str,
1118  const unsigned int inclusive,
1119  const unsigned int exclusive,
1120  const char replace,
1121  struct gc_arena *gc)
1122 {
1123  if (str)
1124  {
1125  char *buf = string_alloc(str, gc);
1126  string_mod(buf, inclusive, exclusive, replace);
1127  return buf;
1128  }
1129  else
1130  {
1131  return NULL;
1132  }
1133 }
1134 
1135 void
1136 string_replace_leading(char *str, const char match, const char replace)
1137 {
1138  ASSERT(match != '\0');
1139  while (*str)
1140  {
1141  if (*str == match)
1142  {
1143  *str = replace;
1144  }
1145  else
1146  {
1147  break;
1148  }
1149  ++str;
1150  }
1151 }
1152 
1153 #ifdef VERIFY_ALIGNMENT
1154 void
1155 valign4(const struct buffer *buf, const char *file, const int line)
1156 {
1157  if (buf && buf->len)
1158  {
1159  int msglevel = D_ALIGN_DEBUG;
1160  const unsigned int u = (unsigned int) BPTR(buf);
1161 
1162  if (u & (PAYLOAD_ALIGN-1))
1163  {
1164  msglevel = D_ALIGN_ERRORS;
1165  }
1166 
1167  msg(msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d",
1168  (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "",
1169  file,
1170  line,
1171  (ptr_type)buf->data,
1172  buf->offset,
1173  buf->len,
1174  buf->capacity,
1175  buf_debug_file(buf),
1176  buf_debug_line(buf));
1177  }
1178 }
1179 #endif /* ifdef VERIFY_ALIGNMENT */
1180 
1181 /*
1182  * struct buffer_list
1183  */
1184 struct buffer_list *
1186 {
1187  struct buffer_list *ret;
1188  ALLOC_OBJ_CLEAR(ret, struct buffer_list);
1189  ret->size = 0;
1190  return ret;
1191 }
1192 
1193 void
1195 {
1196  if (ol)
1197  {
1198  buffer_list_reset(ol);
1199  free(ol);
1200  }
1201 }
1202 
1203 bool
1205 {
1206  return ol && ol->head != NULL;
1207 }
1208 
1209 void
1211 {
1212  struct buffer_entry *e = ol->head;
1213  while (e)
1214  {
1215  struct buffer_entry *next = e->next;
1216  free_buf(&e->buf);
1217  free(e);
1218  e = next;
1219  }
1220  ol->head = ol->tail = NULL;
1221  ol->size = 0;
1222 }
1223 
1224 void
1225 buffer_list_push(struct buffer_list *ol, const char *str)
1226 {
1227  if (str)
1228  {
1229  const size_t len = strlen((const char *)str);
1230  struct buffer_entry *e = buffer_list_push_data(ol, str, len+1);
1231  if (e)
1232  {
1233  e->buf.len = (int)len; /* Don't count trailing '\0' as part of length */
1234  }
1235  }
1236 }
1237 
1238 struct buffer_entry *
1239 buffer_list_push_data(struct buffer_list *ol, const void *data, size_t size)
1240 {
1241  struct buffer_entry *e = NULL;
1242  if (data)
1243  {
1244  ALLOC_OBJ_CLEAR(e, struct buffer_entry);
1245 
1246  ++ol->size;
1247  if (ol->tail)
1248  {
1249  ASSERT(ol->head);
1250  ol->tail->next = e;
1251  }
1252  else
1253  {
1254  ASSERT(!ol->head);
1255  ol->head = e;
1256  }
1257  e->buf = alloc_buf(size);
1258  memcpy(e->buf.data, data, size);
1259  e->buf.len = (int)size;
1260  ol->tail = e;
1261  }
1262  return e;
1263 }
1264 
1265 struct buffer *
1267 {
1268  if (ol && ol->head)
1269  {
1270  return &ol->head->buf;
1271  }
1272  else
1273  {
1274  return NULL;
1275  }
1276 }
1277 
1278 void
1279 buffer_list_aggregate_separator(struct buffer_list *bl, const size_t max_len,
1280  const char *sep)
1281 {
1282  const size_t sep_len = strlen(sep);
1283  struct buffer_entry *more = bl->head;
1284  size_t size = 0;
1285  int count = 0;
1286  for (count = 0; more; ++count)
1287  {
1288  size_t extra_len = BLEN(&more->buf) + sep_len;
1289  if (size + extra_len > max_len)
1290  {
1291  break;
1292  }
1293 
1294  size += extra_len;
1295  more = more->next;
1296  }
1297 
1298  if (count >= 2)
1299  {
1300  struct buffer_entry *f;
1301  ALLOC_OBJ_CLEAR(f, struct buffer_entry);
1302  f->buf = alloc_buf(size + 1); /* prevent 0-byte malloc */
1303 
1304  struct buffer_entry *e = bl->head;
1305  for (size_t i = 0; e && i < count; ++i)
1306  {
1307  struct buffer_entry *next = e->next;
1308  buf_copy(&f->buf, &e->buf);
1309  buf_write(&f->buf, sep, sep_len);
1310  free_buf(&e->buf);
1311  free(e);
1312  e = next;
1313  }
1314  bl->head = f;
1315  bl->size -= count - 1;
1316  f->next = more;
1317  if (!more)
1318  {
1319  bl->tail = f;
1320  }
1321  }
1322 }
1323 
1324 void
1325 buffer_list_aggregate(struct buffer_list *bl, const size_t max)
1326 {
1327  buffer_list_aggregate_separator(bl, max, "");
1328 }
1329 
1330 void
1332 {
1333  if (ol && ol->head)
1334  {
1335  struct buffer_entry *e = ol->head->next;
1336  free_buf(&ol->head->buf);
1337  free(ol->head);
1338  ol->head = e;
1339  --ol->size;
1340  if (!e)
1341  {
1342  ol->tail = NULL;
1343  }
1344  }
1345 }
1346 
1347 void
1349 {
1350  if (ol->head)
1351  {
1352  struct buffer *buf = &ol->head->buf;
1353  ASSERT(buf_advance(buf, n));
1354  if (!BLEN(buf))
1355  {
1356  buffer_list_pop(ol);
1357  }
1358  }
1359 }
1360 
1361 struct buffer_list *
1362 buffer_list_file(const char *fn, int max_line_len)
1363 {
1364  FILE *fp = platform_fopen(fn, "r");
1365  struct buffer_list *bl = NULL;
1366 
1367  if (fp)
1368  {
1369  char *line = (char *) malloc(max_line_len);
1370  if (line)
1371  {
1372  bl = buffer_list_new();
1373  while (fgets(line, max_line_len, fp) != NULL)
1374  {
1375  buffer_list_push(bl, line);
1376  }
1377  free(line);
1378  }
1379  fclose(fp);
1380  }
1381  return bl;
1382 }
1383 
1384 struct buffer
1385 buffer_read_from_file(const char *filename, struct gc_arena *gc)
1386 {
1387  struct buffer ret = { 0 };
1388 
1389  platform_stat_t file_stat = { 0 };
1390  if (platform_stat(filename, &file_stat) < 0)
1391  {
1392  return ret;
1393  }
1394 
1395  FILE *fp = platform_fopen(filename, "r");
1396  if (!fp)
1397  {
1398  return ret;
1399  }
1400 
1401  const size_t size = file_stat.st_size;
1402  ret = alloc_buf_gc(size + 1, gc); /* space for trailing \0 */
1403  size_t read_size = fread(BPTR(&ret), 1, size, fp);
1404  if (read_size == 0)
1405  {
1406  free_buf_gc(&ret, gc);
1407  goto cleanup;
1408  }
1409  ASSERT(buf_inc_len(&ret, (int)read_size));
1410  buf_null_terminate(&ret);
1411 
1412 cleanup:
1413  fclose(fp);
1414  return ret;
1415 }
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:538
buffer_write_file
bool buffer_write_file(const char *filename, const struct buffer *buf)
Write buffer contents to file.
Definition: buffer.c:344
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:1385
CC_BACKSLASH
#define CC_BACKSLASH
backslash
Definition: buffer.h:918
buf_rmtail
void buf_rmtail(struct buffer *buf, uint8_t remove)
Definition: buffer.c:562
error.h
gc_addspecial
void gc_addspecial(void *addr, void(*free_function)(void *), struct gc_arena *a)
Definition: buffer.c:482
string_array_len
int string_array_len(const char **array)
Definition: buffer.c:747
M_ERRNO
#define M_ERRNO
Definition: error.h:100
buf_forward_capacity_total
static int buf_forward_capacity_total(const struct buffer *buf)
Definition: buffer.h:577
CC_SLASH
#define CC_SLASH
slash
Definition: buffer.h:924
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:95
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:919
static_assert
#define static_assert(expr, diagnostic)
Definition: error.h:218
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:934
rm_trailing_chars
void rm_trailing_chars(char *str, const char *what_to_delete)
Definition: buffer.c:667
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:577
CC_CRLF
#define CC_CRLF
carriage return or newline
Definition: buffer.h:938
CC_DASH
#define CC_DASH
dash
Definition: buffer.h:920
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:1266
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:1279
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:730
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:527
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:923
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:904
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:1239
x_gc_freespecial
void x_gc_freespecial(struct gc_arena *a)
Definition: buffer.c:466
CLEAR
#define CLEAR(x)
Definition: basic.h:33
CC_NEWLINE
#define CC_NEWLINE
newline
Definition: buffer.h:915
mtu.h
buffer_list_file
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
Definition: buffer.c:1362
CC_DOUBLE_QUOTE
#define CC_DOUBLE_QUOTE
double quote
Definition: buffer.h:926
platform_stat_t
struct _stat platform_stat_t
Definition: platform.h:146
string_alloc
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:693
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:201
string_clear
void string_clear(char *str)
Definition: buffer.c:735
string_replace_leading
void string_replace_leading(char *str, const char match, const char replace)
Definition: buffer.c:1136
buffer_entry::buf
struct buffer buf
Definition: buffer.h:1122
buf_chomp
void buf_chomp(struct buffer *buf)
Definition: buffer.c:598
buf_advance
static bool buf_advance(struct buffer *buf, int size)
Definition: buffer.h:636
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:608
CC_QUESTION_MARK
#define CC_QUESTION_MARK
question mark
Definition: buffer.h:933
CC_SINGLE_QUOTE
#define CC_SINGLE_QUOTE
single quote
Definition: buffer.h:925
write
@ write
Definition: interactive.c:206
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:710
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:909
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:1085
buffer_entry::next
struct buffer_entry * next
Definition: buffer.h:1123
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:1225
CC_LESS_THAN
#define CC_LESS_THAN
less than sign
Definition: buffer.h:930
FHE_CAPS
#define FHE_CAPS
Definition: buffer.h:516
CC_GREATER_THAN
#define CC_GREATER_THAN
greater than sign
Definition: buffer.h:931
CC_CR
#define CC_CR
carriage return
Definition: buffer.h:916
char_class
bool char_class(const unsigned char c, const unsigned int flags)
Definition: buffer.c:921
convert_to_one_line
void convert_to_one_line(struct buffer *buf)
Definition: buffer.c:329
CC_PIPE
#define CC_PIPE
pipe
Definition: buffer.h:932
CC_EQUAL
#define CC_EQUAL
equal sign
Definition: buffer.h:929
gc_transfer
void gc_transfer(struct gc_arena *dest, struct gc_arena *src)
Definition: buffer.c:504
CC_REVERSE_QUOTE
#define CC_REVERSE_QUOTE
reverse quote
Definition: buffer.h:927
CC_DIGIT
#define CC_DIGIT
digit isdigit()
Definition: buffer.h:908
CC_BLANK
#define CC_BLANK
space or tab
Definition: buffer.h:914
CC_AT
#define CC_AT
at sign
Definition: buffer.h:928
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
buffer_list::size
int size
Definition: buffer.h:1130
buffer_list_new
struct buffer_list * buffer_list_new(void)
Allocate an empty buffer list of capacity max_size.
Definition: buffer.c:1185
CC_SPACE
#define CC_SPACE
whitespace isspace()
Definition: buffer.h:911
CC_ASCII
#define CC_ASCII
ASCII character.
Definition: buffer.h:906
CC_COMMA
#define CC_COMMA
comma
Definition: buffer.h:922
buf_write
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:686
CC_ANY
#define CC_ANY
any character
Definition: buffer.h:901
buffer.h
syshead.h
platform_fopen
FILE * platform_fopen(const char *path, const char *mode)
Definition: platform.c:514
BPTR
#define BPTR(buf)
Definition: buffer.h:124
CC_DOT
#define CC_DOT
dot
Definition: buffer.h:921
np
const char * np(const char *str)
Definition: buffer.c:904
CC_ALPHA
#define CC_ALPHA
alphabetic isalpha()
Definition: buffer.h:905
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:1066
CC_PUNCT
#define CC_PUNCT
punctuation ispunct()
Definition: buffer.h:910
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:624
buffer_list::tail
struct buffer_entry * tail
Definition: buffer.h:1129
buffer_list_pop
void buffer_list_pop(struct buffer_list *ol)
Definition: buffer.c:1331
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:540
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:641
buf_string_match_head_str
bool buf_string_match_head_str(const struct buffer *src, const char *match)
Definition: buffer.c:822
chomp
void chomp(char *str)
Definition: buffer.c:658
PAYLOAD_ALIGN
#define PAYLOAD_ALIGN
Definition: mtu.h:91
FHE_SPACE_BREAK_MASK
#define FHE_SPACE_BREAK_MASK
Definition: buffer.h:515
buf_string_compare_advance
bool buf_string_compare_advance(struct buffer *src, const char *match)
Definition: buffer.c:833
buffer_list_advance
void buffer_list_advance(struct buffer_list *ol, int n)
Definition: buffer.c:1348
gc_malloc
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:380
openvpn_snprintf
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
Definition: buffer.c:294
ptr_type
unsigned long ptr_type
Definition: common.h:58
x_gc_free
void x_gc_free(struct gc_arena *a)
Definition: buffer.c:447
string_alloc_buf
struct buffer string_alloc_buf(const char *str, struct gc_arena *gc)
Definition: buffer.c:796
buffer_list_defined
bool buffer_list_defined(const struct buffer_list *ol)
Checks if the list is valid and non-empty.
Definition: buffer.c:1204
ALLOC_OBJ_CLEAR
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1066
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:653
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:1194
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:1325
gc_entry_special::addr
void * addr
Definition: buffer.h:102
CC_NULL
#define CC_NULL
null character \0
Definition: buffer.h:902
CC_XDIGIT
#define CC_XDIGIT
hex digit isxdigit()
Definition: buffer.h:912
check_malloc_return
static void check_malloc_return(void *p)
Definition: buffer.h:1109
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:847
buf_read_u8
static int buf_read_u8(struct buffer *buf)
Definition: buffer.h:808
platform_open
int platform_open(const char *path, int flags, int mode)
Definition: platform.c:527
buf_forward_capacity
static int buf_forward_capacity(const struct buffer *buf)
Definition: buffer.h:559
print_argv
char * print_argv(const char **p, struct gc_arena *gc, const unsigned int flags)
Definition: buffer.c:761
CC_CNTRL
#define CC_CNTRL
control character iscntrl()
Definition: buffer.h:907
char_inc_exc
static bool char_inc_exc(const char c, const unsigned int inclusive, const unsigned int exclusive)
Definition: buffer.c:1060
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:1210
skip_leading_whitespace
const char * skip_leading_whitespace(const char *str)
Definition: buffer.c:623
buffer_list
Definition: buffer.h:1126
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:1117
msg
#define msg(flags,...)
Definition: error.h:150
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:414
buffer_entry
Definition: buffer.h:1120
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:1128
buf_set_read
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Definition: buffer.h:348
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:313
buf_parse
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Definition: buffer.c:869
cleanup
static int cleanup(void **state)
Definition: test_pkcs11.c:280