The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
print.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Functions to produce and parse the FreeRADIUS presentation format
18  *
19  * @file src/lib/util/print.c
20  *
21  * @copyright 2000,2006 The FreeRADIUS server project
22  */
23 RCSID("$Id: ae8a8f6668b6d155854898ffd05d932a6c8b564d $")
24 
25 #include <freeradius-devel/util/debug.h>
26 #include <freeradius-devel/util/base16.h>
27 #include <freeradius-devel/util/pair.h>
28 
29 
30 /** Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8
31  *
32  * @param[in] str input string.
33  * @param[in] inlen length of input string. May be -1 if str
34  * is \0 terminated.
35  * @return
36  * - 0 if the character is invalid.
37  * - >0 the number of bytes the character consists of.
38  */
39 inline size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
40 {
41  if (inlen == 0) return 0;
42 
43  if (inlen < 0) inlen = 4; /* longest char */
44 
45  if (*str < 0x20) return 0;
46 
47  if (*str <= 0x7e) return 1; /* 1 */
48 
49  if (*str <= 0xc1) return 0;
50 
51  if (inlen < 2) return 0;
52 
53  if ((str[0] >= 0xc2) && /* 2 */
54  (str[0] <= 0xdf) &&
55  (str[1] >= 0x80) &&
56  (str[1] <= 0xbf)) {
57  return 2;
58  }
59 
60  if (inlen < 3) return 0;
61 
62  if ((str[0] == 0xe0) && /* 3 */
63  (str[1] >= 0xa0) &&
64  (str[1] <= 0xbf) &&
65  (str[2] >= 0x80) &&
66  (str[2] <= 0xbf)) {
67  return 3;
68  }
69 
70  if ((str[0] >= 0xe1) && /* 4a */
71  (str[0] <= 0xec) &&
72  (str[1] >= 0x80) &&
73  (str[1] <= 0xbf) &&
74  (str[2] >= 0x80) &&
75  (str[2] <= 0xbf)) {
76  return 3;
77  }
78 
79  if ((str[0] >= 0xee) && /* 4b */
80  (str[0] <= 0xef) &&
81  (str[1] >= 0x80) &&
82  (str[1] <= 0xbf) &&
83  (str[2] >= 0x80) &&
84  (str[2] <= 0xbf)) {
85  return 3;
86  }
87 
88  if ((str[0] == 0xed) && /* 5 */
89  (str[1] >= 0x80) &&
90  (str[1] <= 0x9f) &&
91  (str[2] >= 0x80) &&
92  (str[2] <= 0xbf)) {
93  return 3;
94  }
95 
96  if (inlen < 4) return 0;
97 
98  if ((str[0] == 0xf0) && /* 6 */
99  (str[1] >= 0x90) &&
100  (str[1] <= 0xbf) &&
101  (str[2] >= 0x80) &&
102  (str[2] <= 0xbf) &&
103  (str[3] >= 0x80) &&
104  (str[3] <= 0xbf)) {
105  return 4;
106  }
107 
108  if ((str[0] >= 0xf1) && /* 6 */
109  (str[0] <= 0xf3) &&
110  (str[1] >= 0x80) &&
111  (str[1] <= 0xbf) &&
112  (str[2] >= 0x80) &&
113  (str[2] <= 0xbf) &&
114  (str[3] >= 0x80) &&
115  (str[3] <= 0xbf)) {
116  return 4;
117  }
118 
119 
120  if ((str[0] == 0xf4) && /* 7 */
121  (str[1] >= 0x80) &&
122  (str[1] <= 0x8f) &&
123  (str[2] >= 0x80) &&
124  (str[2] <= 0xbf) &&
125  (str[3] >= 0x80) &&
126  (str[3] <= 0xbf)) {
127  return 4;
128  }
129 
130  /*
131  * Invalid UTF-8 Character
132  */
133  return 0;
134 }
135 
136 /** Validate a complete UTF8 string
137  *
138  * @param[in] str input string.
139  * @param[in] inlen length of input string. May be -1 if str
140  * is \0 terminated.
141  * @return The number of bytes validated. If ret == inlen the entire
142  * string is valid. Else ret gives the offset at which the
143  * first invalid byte sequence was found.
144  */
146 {
147  uint8_t const *p, *end;
148  size_t len;
149 
150  len = inlen < 0 ? strlen((char const *)str) : (size_t) inlen;
151 
152  p = str;
153  end = p + len;
154 
155  do {
156  size_t clen;
157 
158  clen = fr_utf8_char(p, end - p);
159  if (clen == 0) return end - p;
160  p += clen;
161  } while (p < end);
162 
163  return inlen;
164 }
165 
166 /** Return a pointer to the first UTF8 char in a string.
167  *
168  * @param[out] out_chr_len Where to write the length of the multibyte char passed in chr (may be NULL).
169  * @param[in] str Haystack.
170  * @param[in] inlen Length of string (in bytes). Pass -1 to determine the length of the string.
171  * @param[in] chr Multibyte needle.
172  * @return
173  * - Position of chr in str.
174  * - NULL if not found.
175  */
176 char const *fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
177 {
178  char const *p = str, *end;
179  int needle_len;
180 
181  if (inlen < 0) inlen = strlen(str);
182 
183  end = str + inlen;
184 
185  /*
186  * Figure out how big the multibyte sequence
187  * we're looking for is.
188  */
189  needle_len = fr_utf8_char((uint8_t const *)chr, -1);
190  if (needle_len == 0) needle_len = 1; /* Invalid UTF8 sequence - ignore - needle is one byte */
191  if (out_chr_len) *out_chr_len = needle_len;
192 
193  /*
194  * Loop over the input sequence, advancing
195  * UTF8 sequence by utf8 seqnce.
196  */
197  while (p < end) {
198  int schr_len;
199 
200  schr_len = fr_utf8_char((uint8_t const *)p, end - p);
201  if (schr_len == 0) schr_len = 1; /* Invalid UTF8 sequence - ignore - advance by 1 */
202  if (schr_len != needle_len) goto next;
203 
204  /*
205  * See if this matches out multibyte needle
206  */
207  if (memcmp(p, chr, schr_len) == 0) return p;
208  next:
209  p += schr_len;
210  }
211 
212  return NULL;
213 }
214 
215 /** Escape any non printable or non-UTF8 characters in the input string
216  *
217  * @note Return value should be checked with is_truncated
218  * @note Will always \0 terminate unless outlen == 0.
219  *
220  * @param[out] out where to write the escaped string.
221  * @param[out] outlen the length of the buffer pointed to by out.
222  * @param[in] in string to escape.
223  * @param[in] inlen length of string to escape (lets us deal with embedded NULs)
224  * @param[in] quote the quotation character
225  * @return
226  * - The number of bytes written to the out buffer.
227  * - A number >= outlen if truncation has occurred.
228  */
229 size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
230 {
231  uint8_t const *p = (uint8_t const *) in;
232  size_t utf8;
233  size_t used;
234  size_t freespace;
235 
236  /* No input, so no output... */
237  if (!in) {
238  if (out && outlen) *out = '\0';
239  return 0;
240  }
241 
242  /* Figure out the length of the input string */
243  if (inlen < 0) inlen = strlen(in);
244 
245  /*
246  * No quotation character, just use memcpy, ensuring we
247  * don't overflow the output buffer.
248  */
249  if (!quote) {
250  if (!out) return inlen;
251 
252  if ((size_t)inlen >= outlen) {
253  memcpy(out, in, outlen - 1);
254  out[outlen - 1] = '\0';
255  } else {
256  memcpy(out, in, inlen);
257  out[inlen] = '\0';
258  }
259 
260  return inlen;
261  }
262 
263  /*
264  * Check the output buffer and length. Zero both of them
265  * out if either are zero.
266  */
267  freespace = outlen;
268  if (freespace == 0) out = NULL;
269  if (!out) freespace = 0;
270 
271  used = 0;
272 
273  while (inlen > 0) {
274  int sp = 0;
275 
276  /*
277  * Always escape the quotation character.
278  */
279  if (*p == quote) {
280  sp = quote;
281  goto do_escape;
282  }
283 
284  /*
285  * Escape the backslash ONLY for single quoted strings.
286  */
287  if (quote == '\'') {
288  if (*p == '\\') {
289  sp = '\\';
290  }
291  goto do_escape;
292  }
293 
294  /*
295  * Try to convert 0x0a --> \r, etc.
296  * Backslashes get handled specially.
297  */
298  switch (*p) {
299  case '\r':
300  sp = 'r';
301  break;
302 
303  case '\n':
304  sp = 'n';
305  break;
306 
307  case '\t':
308  sp = 't';
309  break;
310 
311  case '\\':
312  sp = '\\';
313  break;
314 
315  default:
316  sp = '\0';
317  break;
318  } /* escape the character at *p */
319 
320  do_escape:
321  if (sp) {
322  if ((freespace > 0) && (freespace <= 2)) {
323  if (out) out[used] = '\0';
324  out = NULL;
325  freespace = 0;
326 
327  } else if (freespace > 2) { /* room for char AND trailing zero */
328  if (out) {
329  out[used] = '\\';
330  out[used + 1] = sp;
331  }
332  freespace -= 2;
333  }
334 
335  used += 2;
336  p++;
337  inlen--;
338  continue;
339  }
340 
341  /*
342  * All strings are UTF-8 clean.
343  */
344  utf8 = fr_utf8_char(p, inlen);
345 
346  /*
347  * If we have an invalid UTF-8 character, it gets
348  * copied over as a 1-byte character for single
349  * quoted strings. Which means that the output
350  * isn't strictly UTF-8, but oh well...
351  *
352  * For double quoted strints, the invalid
353  * characters get escaped as octal encodings.
354  */
355  if (utf8 == 0) {
356  if (quote == '\'') {
357  utf8 = 1;
358 
359  } else {
360  if ((freespace > 0) && (freespace <= 4)) {
361  if (out) out[used] = '\0';
362  out = NULL;
363  freespace = 0;
364 
365  } else if (freespace > 4) { /* room for char AND trailing zero */
366  if (out) snprintf(out + used, freespace, "\\%03o", *p);
367  freespace -= 4;
368  }
369 
370  used += 4;
371  p++;
372  inlen--;
373  continue;
374  }
375  }
376 
377  if ((freespace > 0) && (freespace <= utf8)) {
378  if (out) out[used] = '\0';
379  out = NULL;
380  freespace = 0;
381 
382  } else if (freespace > utf8) { /* room for char AND trailing zero */
383  if (out) memcpy(out + used, p, utf8);
384  freespace -= utf8;
385  }
386 
387  used += utf8;
388  p += utf8;
389  inlen -= utf8;
390  }
391 
392  /*
393  * Ensure that the output buffer is always zero terminated.
394  */
395  if (out && freespace) out[used] = '\0';
396 
397  return used;
398 }
399 
400 /** Find the length of the buffer required to fully escape a string with fr_prints
401  *
402  * Were assuming here that's it's cheaper to figure out the length and do one
403  * alloc than repeatedly expand the buffer when we find extra chars which need
404  * to be added.
405  *
406  * @param in string to calculate the escaped length for.
407  * @param inlen length of the input string, if < 0 strlen will be used to check the length.
408  * @param[in] quote the quotation character.
409  * @return the size of buffer required to hold the escaped string including the NUL byte.
410  */
411 size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
412 {
413  return fr_snprint(NULL, 0, in, inlen, quote) + 1;
414 }
415 
416 /** Escape string that may contain binary data, and write it to a new buffer
417  *
418  * This is useful in situations where we expect printable strings as input,
419  * but under some conditions may get binary data. A good example is libldap
420  * and the arrays of struct berval ldap_get_values_len returns.
421  *
422  * @param[in] ctx To allocate new buffer in.
423  * @param[in] in String to escape.
424  * @param[in] inlen Length of string. Should be >= 0 if the data may contain
425  * embedded \0s. Must be >= 0 if data may not be \0 terminated.
426  * If < 0 inlen will be calculated using strlen.
427  * @param[in] quote the quotation character.
428  * @return new buffer holding the escaped string.
429  */
430 char *fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
431 {
432  size_t len, ret;
433  char *out;
434 
435  len = fr_snprint_len(in, inlen, quote);
436 
437  out = talloc_array(ctx, char, len);
438  ret = fr_snprint(out, len, in, inlen, quote);
439  /*
440  * This is a fatal error, but fr_cond_assert is the strongest
441  * assert we're allowed to use in library functions.
442  */
443  if (!fr_cond_assert(ret == (len - 1))) {
444  talloc_free(out);
445  return NULL;
446  }
447 
448  return out;
449 }
450 
451 DIAG_OFF(format-nonliteral)
452 /** Special version of vasprintf which implements custom format specifiers
453  *
454  * @todo Do something sensible with 'n$', though it's probably not actually used
455  * anywhere in our code base.
456  *
457  * - %pV prints a value box as a string.
458  * - %pM prints a list of value boxes, concatenating them.
459  * - %pH prints a value box as a hex string.
460  * - %pP prints a fr_pair_t.
461  *
462  * This breaks strict compatibility with printf but allows us to continue using
463  * the static format string and argument type validation.
464  *
465  * This same idea is used in Linux for the printk function.
466  *
467  * @param[in] ctx to allocate buffer in.
468  * @param[in] fmt string.
469  * @param[in] ap variadic argument list.
470  * @param[in] suppress_secrets as described
471  * @return
472  * - The result of string interpolation.
473  * - NULL if OOM.
474  */
475 static char *fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
476 {
477  char const *p = fmt, *end = p + strlen(fmt), *fmt_p = p, *fmt_q = p;
478  char *out = NULL, *out_tmp;
479  va_list ap_p, ap_q;
480  char *subst;
481 
482  out = talloc_strdup(ctx, "");
483  va_copy(ap_p, ap);
484  va_copy(ap_q, ap_p);
485 
486  do {
487  char const *q;
488  char len[2] = { '\0', '\0' };
489 
490  subst = NULL;
491 
492  if ((*p != '%') || (*++p == '%')) {
493  fmt_q = p + 1;
494  continue; /* literal char */
495  }
496 
497  /*
498  * Check for parameter field
499  */
500  for (q = p; isdigit((uint8_t) *q); q++);
501  if ((q != p) && (*q == '$')) {
502  p = q + 1;
503  }
504 
505  /*
506  * Check for flags
507  */
508  do {
509  switch (*p) {
510  case '-':
511  continue;
512 
513  case '+':
514  continue;
515 
516  case ' ':
517  continue;
518 
519  case '0':
520  continue;
521 
522  case '#':
523  continue;
524 
525  default:
526  goto done_flags;
527  }
528  } while (++p < end);
529  done_flags:
530 
531  /*
532  * Check for width field. First for strings, and
533  * then for other parameters.
534  */
535  if ((*p == '.') && (*(p + 1) == '*') && (*(p + 2) == 's')) {
536  (void) va_arg(ap_q, int);
537  p += 2;
538  } else if (*p == '*') {
539  (void) va_arg(ap_q, int);
540  p++;
541  } else {
542  for (q = p; isdigit((uint8_t) *q); q++);
543  p = q;
544  }
545 
546  /*
547  * Check for precision field
548  */
549  if (*p == '.') {
550  char *r;
551 
552  p++;
553  (void) strtoul(p, &r, 10);
554  p = r;
555  }
556 
557  /*
558  * Length modifiers
559  */
560  switch (*p) {
561  case 'h':
562  case 'l':
563  len[0] = *p++;
564  if ((*p == 'h') || (*p == 'l')) len[1] = *p++;
565  break;
566 
567  case 'L':
568  case 'z':
569  case 'j':
570  case 't':
571  len[0] = *p++;
572  break;
573  }
574 
575  /*
576  * Types
577  */
578  switch (*p) {
579  case 'i': /* int */
580  case 'd': /* int */
581  case 'u': /* unsigned int */
582  case 'x': /* unsigned int */
583  case 'X': /* unsigned int */
584  case 'o': /* unsigned int */
585  switch (len[0]) {
586  case 'h':
587  if (len[1] == 'h') { /* char (promoted to int) */
588  (void) va_arg(ap_q, int);
589  } else {
590  (void) va_arg(ap_q, int); /* short (promoted to int) */
591  }
592  break;
593 
594  case 'l':
595  if ((*p == 'i') || (*p == 'd')) {
596  if (len[1] == 'l') {
597  (void) va_arg(ap_q, long); /* long */
598  } else {
599  (void) va_arg(ap_q, long long); /* long long */
600  }
601  } else {
602  if (len[1] == 'l') {
603  (void) va_arg(ap_q, unsigned long); /* unsigned long */
604  } else {
605  (void) va_arg(ap_q, unsigned long long);/* unsigned long long */
606  }
607  }
608  break;
609 
610  case 'z':
611  (void) va_arg(ap_q, size_t); /* size_t */
612  break;
613 
614  case 'j':
615  (void) va_arg(ap_q, intmax_t); /* intmax_t */
616  break;
617 
618  case 't':
619  (void) va_arg(ap_q, ptrdiff_t); /* ptrdiff_t */
620  break;
621 
622  case '\0': /* no length modifier */
623  if ((*p == 'i') || (*p == 'd')) {
624  (void) va_arg(ap_q, int); /* int */
625  } else {
626  (void) va_arg(ap_q, unsigned int); /* unsigned int */
627  }
628  }
629  break;
630 
631  case 'f': /* double */
632  case 'F': /* double */
633  case 'e': /* double */
634  case 'E': /* double */
635  case 'g': /* double */
636  case 'G': /* double */
637  case 'a': /* double */
638  case 'A': /* double */
639  switch (len[0]) {
640  case 'L':
641  (void) va_arg(ap_q, long double); /* long double */
642  break;
643 
644  case 'l': /* does nothing */
645  default: /* no length modifier */
646  (void) va_arg(ap_q, double); /* double */
647  }
648  break;
649 
650  case 's':
651  (void) va_arg(ap_q, char *); /* char * */
652  break;
653 
654  case 'c':
655  (void) va_arg(ap_q, int); /* char (promoted to int) */
656  break;
657 
658  case 'p':
659  /*
660  * subst types
661  */
662  switch (*(p + 1)) {
663  case 'V':
664  case 'R':
665  {
666  fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
667  fr_sbuff_escape_rules_t const *e_rules = NULL;
668 
669  /*
670  * Value boxes get escaped as double-quoted strings, unless the value-box
671  * in question is secret, AND we've been asked to hide secrets.
672  *
673  * Note that the secret_rules only hides secrets of data type "string",
674  * which should be good enough for most purposes.
675  */
676  if (*(p + 1) == 'V') {
677  e_rules = &fr_value_escape_double;
678  }
679 
680  /*
681  * Allocations that are not part of the output
682  * string need to occur in the NULL ctx so we don't fragment
683  * any pool associated with it.
684  */
685  if (unlikely(in && in->secret && suppress_secrets)) {
686  subst = talloc_typed_strdup(NULL, "<<< secret >>>");
687 
688  } else if (in) {
689  fr_value_box_aprint(NULL, &subst, in, e_rules);
690  } else {
691  subst = talloc_typed_strdup(NULL, "(null)");
692  }
693 
694  do_splice:
695  if (!subst) goto oom;
696 
697  p++;
698 
699  /*
700  * Pass part of a format string to printf
701  */
702  if (fmt_q != fmt_p) {
703  char *sub_fmt;
704 
705  sub_fmt = talloc_strndup(NULL, fmt_p, fmt_q - fmt_p);
706  out_tmp = talloc_vasprintf_append_buffer(out, sub_fmt, ap_p);
707  talloc_free(sub_fmt);
708  if (!out_tmp) {
709  oom:
710  fr_strerror_const("Out of memory");
711  talloc_free(out);
712  TALLOC_FREE(subst);
713  va_end(ap_p);
714  va_end(ap_q);
715  return NULL;
716  }
717  out = out_tmp;
718 
719  out_tmp = talloc_strdup_append_buffer(out, subst);
720  if (!out_tmp) goto oom;
721  TALLOC_FREE(subst);
722  out = out_tmp;
723 
724  va_end(ap_p); /* one time use only */
725  } else {
726  out_tmp = talloc_strdup_append_buffer(out, subst);
727  if (!out_tmp) goto oom;
728  TALLOC_FREE(subst);
729  out = out_tmp;
730  }
731 
732  va_copy(ap_p, ap_q); /* already advanced to the next argument */
733 
734  fmt_p = p + 1;
735  }
736  break;
737 
738  case 'H':
739  {
740  fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
741 
742  if (!in) {
743  subst = talloc_strdup(NULL, "(null)");
744  goto do_splice;
745  }
746 
747  switch (in->type) {
748  case FR_TYPE_OCTETS:
749  if (in->vb_octets) {
750  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP(in->vb_octets, in->vb_length));
751  } else {
752  subst = talloc_strdup(NULL, "");
753  }
754  break;
755 
756  case FR_TYPE_STRING:
757  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)in->vb_strvalue, in->vb_length));
758  break;
759 
760  default:
761  {
762  fr_value_box_t dst;
763 
764  /*
765  * Convert the boxed value into a octets buffer
766  */
767  if (fr_value_box_cast(NULL, &dst, FR_TYPE_OCTETS, NULL, in) < 0) {
768  subst = talloc_strdup(NULL, fr_strerror()); /* splice in the error */
769  if (!subst) goto oom;
770  }
771 
772  fr_base16_aencode(NULL, &subst, &FR_DBUFF_TMP((uint8_t const *)dst.vb_octets, dst.vb_length));
773  fr_value_box_clear(&dst);
774  break;
775  }
776  }
777  }
778  goto do_splice;
779 
780  case 'M':
781  {
782  fr_value_box_list_t const *in = va_arg(ap_q, fr_value_box_list_t const *);
783 
784  if (!in) {
785  subst = talloc_strdup(NULL, "(null)");
786  goto do_splice;
787  }
788 
789  if (suppress_secrets) {
791  } else {
792  subst = fr_value_box_list_aprint(NULL, in, NULL, &fr_value_escape_double);
793  }
794  }
795  goto do_splice;
796 
797  case 'P':
798  {
799  fr_pair_t const *in = va_arg(ap_q, fr_pair_t const *);
800 
801  if (!in) {
802  subst = talloc_strdup(NULL, "(null)");
803  goto do_splice;
804  }
805 
806  PAIR_VERIFY(in);
807 
808  if (unlikely(in && in->data.secret && suppress_secrets)) {
809  fr_pair_aprint_secure(NULL, &subst, NULL, in);
810  } else {
811  fr_pair_aprint(NULL, &subst, NULL, in);
812  }
813  }
814  goto do_splice;
815 
816  default:
817  (void) va_arg(ap_q, void *); /* void * */
818  }
819  break;
820 
821  case 'n':
822  (void) va_arg(ap_q, int *); /* int * */
823  break;
824 
825  default:
826  break;
827  }
828  fmt_q = p + 1;
829  } while (++p < end);
830 
831  /*
832  * Print out the rest of the format string.
833  */
834  if (*fmt_p) {
835  out_tmp = talloc_vasprintf_append_buffer(out, fmt_p, ap_p);
836  if (!out_tmp) goto oom;
837  out = out_tmp;
838  }
839 
840  va_end(ap_p);
841  va_end(ap_q);
842 
843  /*
844  * One of the above talloc calls sets the type to
845  * be the string. We correct this here so we
846  * don't trigger talloc_aborts later...
847  */
848  talloc_set_type(out, char);
849 
850  return out;
851 }
852 
853 char *fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
854 {
855  return fr_vasprintf_internal(ctx, fmt, ap, false);
856 }
857 
858 char *fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
859 {
860  return fr_vasprintf_internal(ctx, fmt, ap, true);
861 }
862 
863 
864 DIAG_ON(format-nonliteral)
865 
866 /** Special version of asprintf which implements custom format specifiers
867  *
868  * @copybrief fr_vasprintf
869  *
870  * @param[in] ctx to allocate buffer in.
871  * @param[in] fmt string.
872  * @param[in] ... variadic argument list.
873  * @return
874  * - The result of string interpolation.
875  */
876 char *fr_asprintf(TALLOC_CTX *ctx, char const *fmt, ...)
877 {
878  va_list ap;
879  char *ret;
880 
881  va_start(ap, fmt);
882  ret = fr_vasprintf(ctx, fmt, ap);
883  va_end(ap);
884 
885  return ret;
886 }
887 
888 /** Special version of fprintf which implements custom format specifiers
889  *
890  * @copybrief fr_vasprintf
891  *
892  * @param[in] fp to write the result of fmt string.
893  * @param[in] fmt string.
894  * @param[in] ... variadic argument list.
895  * @return
896  * - On success, the number of bytes written is returned (zero indicates nothing was written).
897  * - On error, -1 is returned, and errno is set appropriately
898  */
899 ssize_t fr_fprintf(FILE *fp, char const *fmt, ...)
900 {
901  va_list ap;
902  char *buf;
903  int ret;
904 
905  if (!fp) {
906  fr_strerror_const("Invalid 'fp'");
907  return -1;
908  }
909 
910  va_start(ap, fmt);
911  buf = fr_vasprintf(NULL, fmt, ap);
912  va_end(ap);
913 
914  ret = fputs(buf, fp);
915 
916  TALLOC_FREE(buf);
917 
918  return ret;
919 }
va_end(args)
static int const char * fmt
Definition: acutest.h:573
va_start(args, fmt)
static fr_slen_t fr_base16_aencode(TALLOC_CTX *ctx, char **out, fr_dbuff_t *in)
Convert binary data to a hex string, allocating the output buffer.
Definition: base16.h:71
#define RCSID(id)
Definition: build.h:444
#define DIAG_ON(_x)
Definition: build.h:419
#define unlikely(_x)
Definition: build.h:378
#define DIAG_OFF(_x)
Definition: build.h:418
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition: dbuff.h:509
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
static fr_slen_t in
Definition: dict.h:645
talloc_free(reap)
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
unsigned long int size_t
Definition: merged_model.c:25
static size_t used
ssize_t fr_fprintf(FILE *fp, char const *fmt,...)
Special version of fprintf which implements custom format specifiers.
Definition: print.c:899
size_t fr_snprint(char *out, size_t outlen, char const *in, ssize_t inlen, char quote)
Escape any non printable or non-UTF8 characters in the input string.
Definition: print.c:229
char const * fr_utf8_strchr(int *out_chr_len, char const *str, ssize_t inlen, char const *chr)
Return a pointer to the first UTF8 char in a string.
Definition: print.c:176
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition: print.c:853
char * fr_asprint(TALLOC_CTX *ctx, char const *in, ssize_t inlen, char quote)
Escape string that may contain binary data, and write it to a new buffer.
Definition: print.c:430
ssize_t fr_utf8_str(uint8_t const *str, ssize_t inlen)
Validate a complete UTF8 string.
Definition: print.c:145
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition: print.c:39
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition: print.c:876
size_t fr_snprint_len(char const *in, ssize_t inlen, char quote)
Find the length of the buffer required to fully escape a string with fr_prints.
Definition: print.c:411
static char * fr_vasprintf_internal(TALLOC_CTX *ctx, char const *fmt, va_list ap, bool suppress_secrets)
Special version of vasprintf which implements custom format specifiers.
Definition: print.c:475
char * fr_vasprintf_secure(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition: print.c:858
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:689
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
Definition: talloc.c:333
static fr_slen_t fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print
#define PAIR_VERIFY(_x)
Definition: pair.h:190
static fr_slen_t static vp fr_slen_t fr_pair_aprint_secure(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print_secure
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
#define fr_strerror_const(_msg)
Definition: strerror.h:223
fr_sbuff_escape_rules_t fr_value_escape_double
Definition: value.c:350
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
Definition: value.c:3301
char * fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together.
Definition: value.c:5976
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3672
char * fr_value_box_list_aprint_secure(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim, fr_sbuff_escape_rules_t const *e_rules)
Concatenate the string representations of a list of value boxes together hiding "secret" values.
Definition: value.c:6026
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
static size_t char fr_sbuff_t size_t inlen
Definition: value.h:984
int format(printf, 5, 0))
static size_t char ** out
Definition: value.h:984