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