c0a1aad78dfb4dd3b3823afec8d40dddb66c312b
[exim.git] / src / src / string.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
9
10 /* Miscellaneous string-handling functions. Some are not required for
11 utilities and tests, and are cut out by the COMPILE_UTILITY macro. */
12
13
14 #include "exim.h"
15 #include <assert.h>
16
17
18 #ifndef COMPILE_UTILITY
19 /*************************************************
20 *            Test for IP address                 *
21 *************************************************/
22
23 /* This used just to be a regular expression, but with IPv6 things are a bit
24 more complicated. If the address contains a colon, it is assumed to be a v6
25 address (assuming HAVE_IPV6 is set). If a mask is permitted and one is present,
26 and maskptr is not NULL, its offset is placed there.
27
28 Arguments:
29   s         a string
30   maskptr   NULL if no mask is permitted to follow
31             otherwise, points to an int where the offset of '/' is placed
32             if there is no / followed by trailing digits, *maskptr is set 0
33   errp      NULL if no diagnostic information is required, and if the netmask
34             length should not be checked. Otherwise it is set pointing to a short
35             descriptive text.
36
37 Returns:    0 if the string is not a textual representation of an IP address
38             4 if it is an IPv4 address
39             6 if it is an IPv6 address
40
41 The legacy string_is_ip_address() function follows below.
42 */
43
44 int
45 string_is_ip_addressX(const uschar * ip_addr, int * maskptr, const uschar ** errp)
46 {
47 struct addrinfo hints, * res;
48 uschar * slash, * percent, * endp = NULL;
49 long int mask = 0;
50 const uschar * addr = NULL;
51 int af;
52 union { /* we do not need this, but inet_pton() needs a place for storage */
53   struct in_addr sa4;
54   struct in6_addr sa6;
55 } sa;
56
57 /* If there is a slash, but we didn't request a (optional) netmask,
58 we return failure, as we do if the mask isn't a pure numerical value,
59 or if it is negative. The actual length is checked later, once we know
60 the address family. */
61 if (slash = Ustrchr(ip_addr, '/'))
62   {
63   uschar * rest;
64
65   if (!maskptr)
66     {
67     if (errp) *errp = US"netmask found, but not requested";
68     return 0;
69     }
70
71   mask = Ustrtol(slash+1, &rest, 10);
72   if (*rest || mask < 0)
73     {
74     if (errp) *errp = US"netmask not numeric or <0";
75     return 0;
76     }
77
78   *maskptr = slash - ip_addr;     /* offset of the slash */
79   endp = slash;
80   }
81 else if (maskptr) *maskptr = 0; /* no slash found */
82
83 /* The interface-ID suffix (%<id>) is optional (for IPv6). If it
84 exists, we check it syntactically. Later, if we know the address
85 family is IPv4, we might reject it.
86 The interface-ID is mutually exclusive with the netmask, to the
87 best of my knowledge. */
88
89 if (percent = Ustrchr(ip_addr, '%'))
90   {
91   if (slash)
92     {
93     if (errp) *errp = US"interface-ID and netmask are mutually exclusive";
94     return 0;
95     }
96   for (uschar *p = percent+1; *p; p++)
97     if (!isalnum(*p) && !ispunct(*p))
98       {
99       if (errp) *errp = US"interface-ID must match [[:alnum:][:punct:]]";
100       return 0;
101       }
102   endp = percent;
103   }
104
105 /* inet_pton() can't parse netmasks and interface IDs, so work on a shortened copy
106 allocated on the current stack */
107
108 if (endp)
109   {
110   ptrdiff_t l = endp - ip_addr;
111   if (l > 255)
112     {
113     if (errp) *errp = US"rudiculous long ip address string";
114     return 0;
115     }
116   addr = string_copyn(ip_addr, l);
117   }
118 else
119   addr = ip_addr;
120
121 af = Ustrchr(addr, ':') ? AF_INET6 : AF_INET;
122 if (!inet_pton(af, CCS addr, &sa))
123   {
124   if (errp) *errp = af == AF_INET6 ? US"IP address string not parsable as IPv6"
125                                    : US"IP address string not parsable IPv4";
126   return 0;
127   }
128
129 /* we do not check the values of the mask here, as
130 this is done on the callers side (but I don't understand why), so
131 actually I'd like to do it here, but it breaks at least testcase 0002 */
132
133 switch (af)
134   {
135   case AF_INET6:
136       if (errp && mask > 128)
137         {
138         *errp = US"IPv6 netmask value must not be >128";
139         return 0;
140         }
141       return 6;
142   case AF_INET:
143       if (percent)
144         {
145         if (errp) *errp = US"IPv4 address string must not have an interface-ID";
146         return 0;
147         }
148       if (errp && mask > 32)
149         {
150         *errp = US"IPv4 netmask value must not be >32";
151         return 0;
152         }
153       return 4;
154   default:
155       if (errp) *errp = US"unknown address family (should not happen)";
156       return 0;
157   }
158 }
159
160
161 int
162 string_is_ip_address(const uschar * ip_addr, int * maskptr)
163 {
164 return string_is_ip_addressX(ip_addr, maskptr, 0);
165 }
166
167 #endif  /* COMPILE_UTILITY */
168
169
170 /*************************************************
171 *              Format message size               *
172 *************************************************/
173
174 /* Convert a message size in bytes to printing form, rounding
175 according to the magnitude of the number. A value of zero causes
176 a string of spaces to be returned.
177
178 Arguments:
179   size        the message size in bytes
180   buffer      where to put the answer
181
182 Returns:      pointer to the buffer
183               a string of exactly 5 characters is normally returned
184 */
185
186 uschar *
187 string_format_size(int size, uschar *buffer)
188 {
189 if (size == 0) Ustrcpy(buffer, US"     ");
190 else if (size < 1024) sprintf(CS buffer, "%5d", size);
191 else if (size < 10*1024)
192   sprintf(CS buffer, "%4.1fK", (double)size / 1024.0);
193 else if (size < 1024*1024)
194   sprintf(CS buffer, "%4dK", (size + 512)/1024);
195 else if (size < 10*1024*1024)
196   sprintf(CS buffer, "%4.1fM", (double)size / (1024.0 * 1024.0));
197 else
198   sprintf(CS buffer, "%4dM", (size + 512 * 1024)/(1024*1024));
199 return buffer;
200 }
201
202
203
204 #ifndef COMPILE_UTILITY
205 /*************************************************
206 *       Convert a number to base 62 format       *
207 *************************************************/
208
209 /* Convert a long integer into an ASCII base 62 string. For Cygwin the value of
210 BASE_62 is actually 36. Always return exactly 6 characters plus a NUL, in a
211 static area.  This is enough for a 32b input, for 62  (for 64b we would want 11+nul);
212 but with 36 we lose half the input range of a 32b input.
213
214 Argument: a long integer
215 Returns:  pointer to base 62 string
216 */
217
218 uschar *
219 string_base62_32(unsigned long int value)
220 {
221 static uschar yield[7];
222 uschar * p = yield + sizeof(yield) - 1;
223 *p = 0;
224 while (p > yield)
225   {
226   *--p = base62_chars[value % BASE_62];
227   value /= BASE_62;
228   }
229 return yield;
230 }
231
232 uschar *
233 string_base62_64(unsigned long int value)
234 {
235 static uschar yield[12];
236 uschar * p = yield + sizeof(yield) - 1;
237 *p = '\0';
238 while (p > yield)
239   if (value)
240     {
241     *--p = base62_chars[value % BASE_62];
242     value /= BASE_62;
243     }
244   else
245     *--p = '0';
246 return yield;
247 }
248 #endif  /* COMPILE_UTILITY */
249
250
251
252 /*************************************************
253 *          Interpret escape sequence             *
254 *************************************************/
255
256 /* This function is called from several places where escape sequences are to be
257 interpreted in strings.
258
259 Arguments:
260   pp       points a pointer to the initiating "\" in the string;
261            the pointer gets updated to point to the final character
262            If the backslash is the last character in the string, it
263            is not interpreted.
264 Returns:   the value of the character escape
265 */
266
267 int
268 string_interpret_escape(const uschar **pp)
269 {
270 #ifdef COMPILE_UTILITY
271 const uschar *hex_digits= CUS"0123456789abcdef";
272 #endif
273 int ch;
274 const uschar *p = *pp;
275 ch = *(++p);
276 if (ch == '\0') return **pp;
277 if (isdigit(ch) && ch != '8' && ch != '9')
278   {
279   ch -= '0';
280   if (isdigit(p[1]) && p[1] != '8' && p[1] != '9')
281     {
282     ch = ch * 8 + *(++p) - '0';
283     if (isdigit(p[1]) && p[1] != '8' && p[1] != '9')
284       ch = ch * 8 + *(++p) - '0';
285     }
286   }
287 else switch(ch)
288   {
289   case 'b':  ch = '\b'; break;
290   case 'f':  ch = '\f'; break;
291   case 'n':  ch = '\n'; break;
292   case 'r':  ch = '\r'; break;
293   case 't':  ch = '\t'; break;
294   case 'v':  ch = '\v'; break;
295   case 'x':
296   ch = 0;
297   if (isxdigit(p[1]))
298     {
299     ch = ch * 16 +
300       Ustrchr(hex_digits, tolower(*(++p))) - hex_digits;
301     if (isxdigit(p[1])) ch = ch * 16 +
302       Ustrchr(hex_digits, tolower(*(++p))) - hex_digits;
303     }
304   break;
305   }
306 *pp = p;
307 return ch;
308 }
309
310
311
312 #ifndef COMPILE_UTILITY
313 /*************************************************
314 *          Ensure string is printable            *
315 *************************************************/
316
317 /* This function is called for critical strings. It checks for any
318 non-printing characters, and if any are found, it makes a new copy
319 of the string with suitable escape sequences. It is most often called by the
320 macro string_printing(), which sets flags to 0.
321
322 Arguments:
323   s             the input string
324   flags         Bit 0: convert tabs.  Bit 1: convert spaces.
325
326 Returns:        string with non-printers encoded as printing sequences
327 */
328
329 const uschar *
330 string_printing2(const uschar *s, int flags)
331 {
332 int nonprintcount = 0;
333 int length = 0;
334 const uschar *t = s;
335 uschar *ss, *tt;
336
337 while (*t)
338   {
339   int c = *t++;
340   if (  !mac_isprint(c)
341      || flags & SP_TAB && c == '\t'
342      || flags & SP_SPACE && c == ' '
343      ) nonprintcount++;
344   length++;
345   }
346
347 if (nonprintcount == 0) return s;
348
349 /* Get a new block of store guaranteed big enough to hold the
350 expanded string. */
351
352 tt = ss = store_get(length + nonprintcount * 3 + 1, s);
353
354 /* Copy everything, escaping non printers. */
355
356 for (t = s; *t; )
357   {
358   int c = *t;
359   if (  mac_isprint(c)
360      && (!(flags & SP_TAB) || c != '\t')
361      && (!(flags & SP_SPACE) || c != ' ')
362      )
363     *tt++ = *t++;
364   else
365     {
366     *tt++ = '\\';
367     switch (*t)
368       {
369       case '\n': *tt++ = 'n'; break;
370       case '\r': *tt++ = 'r'; break;
371       case '\b': *tt++ = 'b'; break;
372       case '\v': *tt++ = 'v'; break;
373       case '\f': *tt++ = 'f'; break;
374       case '\t': *tt++ = 't'; break;
375       default: sprintf(CS tt, "%03o", *t); tt += 3; break;
376       }
377     t++;
378     }
379   }
380 *tt = 0;
381 return ss;
382 }
383 #endif  /* COMPILE_UTILITY */
384
385 /*************************************************
386 *        Undo printing escapes in string         *
387 *************************************************/
388
389 /* This function is the reverse of string_printing2.  It searches for
390 backslash characters and if any are found, it makes a new copy of the
391 string with escape sequences parsed.  Otherwise it returns the original
392 string.
393
394 Arguments:
395   s             the input string
396
397 Returns:        string with printing escapes parsed back
398 */
399
400 uschar *
401 string_unprinting(uschar *s)
402 {
403 uschar *p, *q, *r, *ss;
404 int len, off;
405
406 p = Ustrchr(s, '\\');
407 if (!p) return s;
408
409 len = Ustrlen(s) + 1;
410 ss = store_get(len, s);
411
412 q = ss;
413 off = p - s;
414 if (off)
415   {
416   memcpy(q, s, off);
417   q += off;
418   }
419
420 while (*p)
421   {
422   if (*p == '\\')
423     {
424     *q++ = string_interpret_escape((const uschar **)&p);
425     p++;
426     }
427   else
428     {
429     r = Ustrchr(p, '\\');
430     if (!r)
431       {
432       off = Ustrlen(p);
433       memcpy(q, p, off);
434       p += off;
435       q += off;
436       break;
437       }
438     else
439       {
440       off = r - p;
441       memcpy(q, p, off);
442       q += off;
443       p = r;
444       }
445     }
446   }
447 *q = '\0';
448
449 return ss;
450 }
451
452
453
454
455 #if (defined(HAVE_LOCAL_SCAN) || defined(EXPAND_DLFUNC)) \
456         && !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
457 /*************************************************
458 *            Copy and save string                *
459 *************************************************/
460
461 /*
462 Argument: string to copy
463 Returns:  copy of string in new store with the same taint status
464 */
465
466 uschar *
467 string_copy_function(const uschar * s)
468 {
469 return string_copy_taint(s, s);
470 }
471
472 /* As above, but explicitly specifying the result taint status
473 */
474
475 uschar *
476 string_copy_taint_function(const uschar * s, const void * proto_mem)
477 {
478 return string_copy_taint(s, proto_mem);
479 }
480
481
482
483 /*************************************************
484 *       Copy and save string, given length       *
485 *************************************************/
486
487 /* It is assumed the data contains no zeros. A zero is added
488 onto the end.
489
490 Arguments:
491   s         string to copy
492   n         number of characters
493
494 Returns:    copy of string in new store
495 */
496
497 uschar *
498 string_copyn_function(const uschar * s, int n)
499 {
500 return string_copyn(s, n);
501 }
502 #endif
503
504
505 /*************************************************
506 *     Copy and save string in malloc'd store     *
507 *************************************************/
508
509 /* This function assumes that memcpy() is faster than strcpy().
510
511 Argument: string to copy
512 Returns:  copy of string in new store
513 */
514
515 uschar *
516 string_copy_malloc(const uschar * s)
517 {
518 int len = Ustrlen(s) + 1;
519 uschar * ss = store_malloc(len);
520 memcpy(ss, s, len);
521 return ss;
522 }
523
524
525
526 /*************************************************
527 *    Copy string if long, inserting newlines     *
528 *************************************************/
529
530 /* If the given string is longer than 75 characters, it is copied, and within
531 the copy, certain space characters are converted into newlines.
532
533 Argument:  pointer to the string
534 Returns:   pointer to the possibly altered string
535 */
536
537 uschar *
538 string_split_message(uschar * msg)
539 {
540 uschar *s, *ss;
541
542 if (!msg || Ustrlen(msg) <= 75) return msg;
543 s = ss = msg = string_copy(msg);
544
545 for (;;)
546   {
547   int i = 0;
548   while (i < 75 && *ss && *ss != '\n') ss++, i++;
549   if (!*ss) break;
550   if (*ss == '\n')
551     s = ++ss;
552   else
553     {
554     uschar * t = ss + 1;
555     uschar * tt = NULL;
556     while (--t > s + 35)
557       {
558       if (*t == ' ')
559         {
560         if (t[-1] == ':') { tt = t; break; }
561         if (!tt) tt = t;
562         }
563       }
564
565     if (!tt)          /* Can't split behind - try ahead */
566       {
567       t = ss + 1;
568       while (*t)
569         {
570         if (*t == ' ' || *t == '\n')
571           { tt = t; break; }
572         t++;
573         }
574       }
575
576     if (!tt) break;   /* Can't find anywhere to split */
577     *tt = '\n';
578     s = ss = tt+1;
579     }
580   }
581
582 return msg;
583 }
584
585
586
587 /*************************************************
588 *   Copy returned DNS domain name, de-escaping   *
589 *************************************************/
590
591 /* If a domain name contains top-bit characters, some resolvers return
592 the fully qualified name with those characters turned into escapes. The
593 convention is a backslash followed by _decimal_ digits. We convert these
594 back into the original binary values. This will be relevant when
595 allow_utf8_domains is set true and UTF-8 characters are used in domain
596 names. Backslash can also be used to escape other characters, though we
597 shouldn't come across them in domain names.
598
599 Argument:   the domain name string
600 Returns:    copy of string in new store, de-escaped
601 */
602
603 uschar *
604 string_copy_dnsdomain(uschar * s)
605 {
606 uschar * yield;
607 uschar * ss = yield = store_get(Ustrlen(s) + 1, GET_TAINTED);   /* always treat as tainted */
608
609 while (*s)
610   {
611   if (*s != '\\')
612     *ss++ = *s++;
613   else if (isdigit(s[1]))
614     {
615     *ss++ = (s[1] - '0')*100 + (s[2] - '0')*10 + s[3] - '0';
616     s += 4;
617     }
618   else if (*++s)
619     *ss++ = *s++;
620   }
621
622 *ss = 0;
623 return yield;
624 }
625
626
627 #ifndef COMPILE_UTILITY
628 /*************************************************
629 *     Copy space-terminated or quoted string     *
630 *************************************************/
631
632 /* This function copies from a string until its end, or until whitespace is
633 encountered, unless the string begins with a double quote, in which case the
634 terminating quote is sought, and escaping within the string is done. The length
635 of a de-quoted string can be no longer than the original, since escaping always
636 turns n characters into 1 character.
637
638 Argument:  pointer to the pointer to the first character, which gets updated
639 Returns:   the new string
640 */
641
642 uschar *
643 string_dequote(const uschar ** sptr)
644 {
645 const uschar * s = * sptr;
646 uschar * t, * yield;
647
648 /* First find the end of the string */
649
650 if (*s != '\"')
651   while (*s && !isspace(*s)) s++;
652 else
653   {
654   s++;
655   while (*s && *s != '\"')
656     {
657     if (*s == '\\') (void)string_interpret_escape(&s);
658     s++;
659     }
660   if (*s) s++;
661   }
662
663 /* Get enough store to copy into */
664
665 t = yield = store_get(s - *sptr + 1, *sptr);
666 s = *sptr;
667
668 /* Do the copy */
669
670 if (*s != '\"')
671   while (*s && !isspace(*s)) *t++ = *s++;
672 else
673   {
674   s++;
675   while (*s && *s != '\"')
676     {
677     *t++ = *s == '\\' ? string_interpret_escape(&s) : *s;
678     s++;
679     }
680   if (*s) s++;
681   }
682
683 /* Update the pointer and return the terminated copy */
684
685 *sptr = s;
686 *t = 0;
687 return yield;
688 }
689 #endif  /* COMPILE_UTILITY */
690
691
692
693 /*************************************************
694 *          Format a string and save it           *
695 *************************************************/
696
697 /* The formatting is done by string_vformat, which checks the length of
698 everything.  Taint is taken from the worst of the arguments.
699
700 Arguments:
701   format    a printf() format - deliberately char * rather than uschar *
702               because it will most usually be a literal string
703   func      caller, for debug
704   line      caller, for debug
705   ...       arguments for format
706
707 Returns:    pointer to fresh piece of store containing sprintf'ed string
708 */
709
710 uschar *
711 string_sprintf_trc(const char * format, const uschar * func, unsigned line, ...)
712 {
713 #ifdef COMPILE_UTILITY
714 uschar buffer[STRING_SPRINTF_BUFFER_SIZE];
715 gstring gs = { .size = STRING_SPRINTF_BUFFER_SIZE, .ptr = 0, .s = buffer };
716 gstring * g = &gs;
717 unsigned flags = 0;
718 #else
719 gstring * g = NULL;
720 unsigned flags = SVFMT_REBUFFER|SVFMT_EXTEND;
721 #endif
722
723 va_list ap;
724 va_start(ap, line);
725 g = string_vformat_trc(g, func, line, STRING_SPRINTF_BUFFER_SIZE,
726         flags, format, ap);
727 va_end(ap);
728
729 if (!g)
730   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
731     "string_sprintf expansion was longer than %d; format string was (%s)\n"
732     " called from %s %d\n",
733     STRING_SPRINTF_BUFFER_SIZE, format, func, line);
734
735 #ifdef COMPILE_UTILITY
736 return string_copyn(g->s, g->ptr);
737 #else
738 gstring_release_unused(g);
739 return string_from_gstring(g);
740 #endif
741 }
742
743
744
745 /*************************************************
746 *         Case-independent strncmp() function    *
747 *************************************************/
748
749 /*
750 Arguments:
751   s         first string
752   t         second string
753   n         number of characters to compare
754
755 Returns:    < 0, = 0, or > 0, according to the comparison
756 */
757
758 int
759 strncmpic(const uschar * s, const uschar * t, int n)
760 {
761 while (n--)
762   {
763   int c = tolower(*s++) - tolower(*t++);
764   if (c) return c;
765   }
766 return 0;
767 }
768
769
770 /*************************************************
771 *         Case-independent strcmp() function     *
772 *************************************************/
773
774 /*
775 Arguments:
776   s         first string
777   t         second string
778
779 Returns:    < 0, = 0, or > 0, according to the comparison
780 */
781
782 int
783 strcmpic(const uschar * s, const uschar * t)
784 {
785 while (*s)
786   {
787   int c = tolower(*s++) - tolower(*t++);
788   if (c != 0) return c;
789   }
790 return *t;
791 }
792
793
794 /*************************************************
795 *         Case-independent strstr() function     *
796 *************************************************/
797
798 /* The third argument specifies whether whitespace is required
799 to follow the matched string.
800
801 Arguments:
802   s              string to search
803   t              substring to search for
804   space_follows  if TRUE, match only if whitespace follows
805
806 Returns:         pointer to substring in string, or NULL if not found
807 */
808
809 const uschar *
810 strstric_c(const uschar * s, const uschar * t, BOOL space_follows)
811 {
812 const uschar * p = t;
813 const uschar * yield = NULL;
814 int cl = tolower(*p);
815 int cu = toupper(*p);
816
817 while (*s)
818   {
819   if (*s == cl || *s == cu)
820     {
821     if (!yield) yield = s;
822     if (!*++p)
823       {
824       if (!space_follows || s[1] == ' ' || s[1] == '\n' ) return yield;
825       yield = NULL;
826       p = t;
827       }
828     cl = tolower(*p);
829     cu = toupper(*p);
830     s++;
831     }
832   else if (yield)
833     {
834     yield = NULL;
835     p = t;
836     cl = tolower(*p);
837     cu = toupper(*p);
838     }
839   else s++;
840   }
841 return NULL;
842 }
843
844 uschar *
845 strstric(uschar * s, uschar * t, BOOL space_follows)
846 {
847 return US strstric_c(s, t, space_follows);
848 }
849
850
851 #ifdef COMPILE_UTILITY
852 /* Dummy version for this function; it should never be called */
853 static void
854 gstring_grow(gstring * g, int count)
855 {
856 assert(FALSE);
857 }
858 #endif
859
860
861
862 #ifndef COMPILE_UTILITY
863 /*************************************************
864 *       Get next string from separated list      *
865 *************************************************/
866
867 /* Leading and trailing space is removed from each item. The separator in the
868 list is controlled by the int pointed to by the separator argument as follows:
869
870   If the value is > 0 it is used as the separator. This is typically used for
871   sublists such as slash-separated options. The value is always a printing
872   character.
873
874     (If the value is actually > UCHAR_MAX there is only one item in the list.
875     This is used for some cases when called via functions that sometimes
876     plough through lists, and sometimes are given single items.)
877
878   If the value is <= 0, the string is inspected for a leading <x, where x is an
879   ispunct() or an iscntrl() character. If found, x is used as the separator. If
880   not found:
881
882       (a) if separator == 0, ':' is used
883       (b) if separator <0, -separator is used
884
885   In all cases the value of the separator that is used is written back to the
886   int so that it is used on subsequent calls as we progress through the list.
887
888 A literal ispunct() separator can be represented in an item by doubling, but
889 there is no way to include an iscntrl() separator as part of the data.
890
891 Arguments:
892   listptr    points to a pointer to the current start of the list; the
893              pointer gets updated to point after the end of the next item
894   separator  a pointer to the separator character in an int (see above)
895   buffer     where to put a copy of the next string in the list; or
896                NULL if the next string is returned in new memory
897              Note that if the list is tainted then a provided buffer must be
898              also (else we trap, with a message referencing the callsite).
899              If we do the allocation, taint is handled there.
900   buflen     when buffer is not NULL, the size of buffer; otherwise ignored
901
902   func       caller, for debug
903   line       caller, for debug
904
905 Returns:     pointer to buffer, containing the next substring,
906              or NULL if no more substrings
907 */
908
909 uschar *
910 string_nextinlist_trc(const uschar ** listptr, int * separator, uschar * buffer,
911   int buflen, const uschar * func, int line)
912 {
913 int sep = *separator;
914 const uschar * s = *listptr;
915 BOOL sep_is_special;
916
917 if (!s) return NULL;
918
919 /* This allows for a fixed specified separator to be an iscntrl() character,
920 but at the time of implementation, this is never the case. However, it's best
921 to be conservative. */
922
923 while (isspace(*s) && *s != sep) s++;
924
925 /* A change of separator is permitted, so look for a leading '<' followed by an
926 allowed character. */
927
928 if (sep <= 0)
929   {
930   if (*s == '<' && (ispunct(s[1]) || iscntrl(s[1])))
931     {
932     sep = s[1];
933     if (*++s) ++s;
934     while (isspace(*s) && *s != sep) s++;
935     }
936   else
937     sep = sep ? -sep : ':';
938   *separator = sep;
939   }
940
941 /* An empty string has no list elements */
942
943 if (!*s) return NULL;
944
945 /* Note whether whether or not the separator is an iscntrl() character. */
946
947 sep_is_special = iscntrl(sep);
948
949 /* Handle the case when a buffer is provided. */
950 /*XXX need to also deal with qouted-requirements mismatch */
951
952 if (buffer)
953   {
954   int p = 0;
955   if (is_tainted(s) && !is_tainted(buffer))
956     die_tainted(US"string_nextinlist", func, line);
957   for (; *s; s++)
958     {
959     if (*s == sep && (*(++s) != sep || sep_is_special)) break;
960     if (p < buflen - 1) buffer[p++] = *s;
961     }
962   while (p > 0 && isspace(buffer[p-1])) p--;
963   buffer[p] = '\0';
964   }
965
966 /* Handle the case when a buffer is not provided. */
967
968 else
969   {
970   gstring * g = NULL;
971
972   /* We know that *s != 0 at this point. However, it might be pointing to a
973   separator, which could indicate an empty string, or (if an ispunct()
974   character) could be doubled to indicate a separator character as data at the
975   start of a string. Avoid getting working memory for an empty item. */
976
977   if (*s == sep)
978     if (*++s != sep || sep_is_special)
979       {
980       *listptr = s;
981       return string_copy(US"");
982       }
983
984   /* Not an empty string; the first character is guaranteed to be a data
985   character. */
986
987   for (;;)
988     {
989     const uschar * ss;
990     for (ss = s + 1; *ss && *ss != sep; ) ss++;
991     g = string_catn(g, s, ss-s);
992     s = ss;
993     if (!*s || *++s != sep || sep_is_special) break;
994     }
995
996   /* Trim trailing spaces from the returned string */
997
998   /* while (g->ptr > 0 && isspace(g->s[g->ptr-1])) g->ptr--; */
999   while (  g->ptr > 0 && isspace(g->s[g->ptr-1])
1000         && (g->ptr == 1 || g->s[g->ptr-2] != '\\') )
1001     g->ptr--;
1002   buffer = string_from_gstring(g);
1003   gstring_release_unused_trc(g, CCS func, line);
1004   }
1005
1006 /* Update the current pointer and return the new string */
1007
1008 *listptr = s;
1009 return buffer;
1010 }
1011
1012
1013 static const uschar *
1014 Ustrnchr(const uschar * s, int c, unsigned * len)
1015 {
1016 unsigned siz = *len;
1017 while (siz)
1018   {
1019   if (!*s) return NULL;
1020   if (*s == c)
1021     {
1022     *len = siz;
1023     return s;
1024     }
1025   s++;
1026   siz--;
1027   }
1028 return NULL;
1029 }
1030
1031
1032 /************************************************
1033 *       Add element to separated list           *
1034 ************************************************/
1035 /* This function is used to build a list, returning an allocated null-terminated
1036 growable string. The given element has any embedded separator characters
1037 doubled.
1038
1039 Despite having the same growable-string interface as string_cat() the list is
1040 always returned null-terminated.
1041
1042 Arguments:
1043   list  expanding-string for the list that is being built, or NULL
1044         if this is a new list that has no contents yet
1045   sep   list separator character
1046   ele   new element to be appended to the list
1047
1048 Returns:  pointer to the start of the list, changed if copied for expansion.
1049 */
1050
1051 gstring *
1052 string_append_listele(gstring * list, uschar sep, const uschar * ele)
1053 {
1054 uschar * sp;
1055
1056 if (list && list->ptr)
1057   list = string_catn(list, &sep, 1);
1058
1059 while((sp = Ustrchr(ele, sep)))
1060   {
1061   list = string_catn(list, ele, sp-ele+1);
1062   list = string_catn(list, &sep, 1);
1063   ele = sp+1;
1064   }
1065 list = string_cat(list, ele);
1066 (void) string_from_gstring(list);
1067 return list;
1068 }
1069
1070
1071 gstring *
1072 string_append_listele_n(gstring * list, uschar sep, const uschar * ele,
1073  unsigned len)
1074 {
1075 const uschar * sp;
1076
1077 if (list && list->ptr)
1078   list = string_catn(list, &sep, 1);
1079
1080 while((sp = Ustrnchr(ele, sep, &len)))
1081   {
1082   list = string_catn(list, ele, sp-ele+1);
1083   list = string_catn(list, &sep, 1);
1084   ele = sp+1;
1085   len--;
1086   }
1087 list = string_catn(list, ele, len);
1088 (void) string_from_gstring(list);
1089 return list;
1090 }
1091
1092
1093
1094 /* A slightly-bogus listmaker utility; the separator is a string so
1095 can be multiple chars - there is no checking for the element content
1096 containing any of the separator. */
1097
1098 gstring *
1099 string_append2_listele_n(gstring * list, const uschar * sepstr,
1100  const uschar * ele, unsigned len)
1101 {
1102 if (list && list->ptr)
1103   list = string_cat(list, sepstr);
1104
1105 list = string_catn(list, ele, len);
1106 (void) string_from_gstring(list);
1107 return list;
1108 }
1109
1110
1111
1112 /************************************************/
1113 /* Add more space to a growable-string.  The caller should check
1114 first if growth is required.  The gstring struct is modified on
1115 return; specifically, the string-base-pointer may have been changed.
1116
1117 Arguments:
1118   g             the growable-string
1119   count         amount needed for g->ptr to increase by
1120 */
1121
1122 static void
1123 gstring_grow(gstring * g, int count)
1124 {
1125 int p = g->ptr;
1126 int oldsize = g->size;
1127
1128 /* Mostly, string_cat() is used to build small strings of a few hundred
1129 characters at most. There are times, however, when the strings are very much
1130 longer (for example, a lookup that returns a vast number of alias addresses).
1131 To try to keep things reasonable, we use increments whose size depends on the
1132 existing length of the string. */
1133
1134 unsigned inc = oldsize < 4096 ? 127 : 1023;
1135
1136 if (g->ptr < 0 || g->ptr > g->size || g->size >= INT_MAX/2)
1137   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1138     "internal error in gstring_grow (ptr %d size %d)", g->ptr, g->size);
1139
1140 if (count <= 0) return;
1141
1142 if (count >= INT_MAX/2 - g->ptr)
1143   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1144     "internal error in gstring_grow (ptr %d count %d)", g->ptr, count);
1145
1146 g->size = (p + count + inc + 1) & ~inc;         /* one for a NUL */
1147
1148 /* Try to extend an existing allocation. If the result of calling
1149 store_extend() is false, either there isn't room in the current memory block,
1150 or this string is not the top item on the dynamic store stack. We then have
1151 to get a new chunk of store and copy the old string. When building large
1152 strings, it is helpful to call store_release() on the old string, to release
1153 memory blocks that have become empty. (The block will be freed if the string
1154 is at its start.) However, we can do this only if we know that the old string
1155 was the last item on the dynamic memory stack. This is the case if it matches
1156 store_last_get. */
1157
1158 if (!store_extend(g->s, oldsize, g->size))
1159   g->s = store_newblock(g->s, g->size, p);
1160 }
1161
1162
1163
1164 /*************************************************
1165 *             Add chars to string                *
1166 *************************************************/
1167 /* This function is used when building up strings of unknown length. Room is
1168 always left for a terminating zero to be added to the string that is being
1169 built. This function does not require the string that is being added to be NUL
1170 terminated, because the number of characters to add is given explicitly. It is
1171 sometimes called to extract parts of other strings.
1172
1173 Arguments:
1174   g        growable-string that is being built, or NULL if not assigned yet
1175   s        points to characters to add
1176   count    count of characters to add; must not exceed the length of s, if s
1177              is a C string.
1178
1179 Returns:   growable string, changed if copied for expansion.
1180            Note that a NUL is not added, though space is left for one. This is
1181            because string_cat() is often called multiple times to build up a
1182            string - there's no point adding the NUL till the end.
1183            NULL is a possible return.
1184
1185 */
1186 /* coverity[+alloc] */
1187
1188 gstring *
1189 string_catn(gstring * g, const uschar * s, int count)
1190 {
1191 int p;
1192
1193 if (count < 0)
1194   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1195     "internal error in string_catn (count %d)", count);
1196 if (count == 0) return g;
1197
1198 /*debug_printf("string_catn '%.*s'\n", count, s);*/
1199 if (!g)
1200   {
1201   unsigned inc = count < 4096 ? 127 : 1023;
1202   unsigned size = ((count + inc) &  ~inc) + 1;  /* round up requested count */
1203   g = string_get_tainted(size, s);
1204   }
1205 else if (!g->s)                 /* should not happen */
1206   {
1207   g->s = string_copyn(s, count);
1208   g->ptr = count;
1209   g->size = count;      /*XXX suboptimal*/
1210   return g;
1211   }
1212 else if (is_incompatible(g->s, s))
1213   {
1214 /* debug_printf("rebuf A\n"); */
1215   gstring_rebuffer(g, s);
1216   }
1217
1218 if (g->ptr < 0 || g->ptr > g->size)
1219   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1220     "internal error in string_catn (ptr %d size %d)", g->ptr, g->size);
1221
1222 p = g->ptr;
1223 if (count >= g->size - p)
1224   gstring_grow(g, count);
1225
1226 /* Because we always specify the exact number of characters to copy, we can
1227 use memcpy(), which is likely to be more efficient than strncopy() because the
1228 latter has to check for zero bytes. */
1229
1230 memcpy(g->s + p, s, count);
1231 g->ptr = p + count;
1232 return g;
1233 }
1234
1235
1236 gstring *
1237 string_cat(gstring * g, const uschar * s)
1238 {
1239 return string_catn(g, s, Ustrlen(s));
1240 }
1241
1242
1243
1244 /*************************************************
1245 *        Append strings to another string        *
1246 *************************************************/
1247
1248 /* This function can be used to build a string from many other strings.
1249 It calls string_cat() to do the dirty work.
1250
1251 Arguments:
1252   g        growable-string that is being built, or NULL if not yet assigned
1253   count    the number of strings to append
1254   ...      "count" uschar* arguments, which must be valid zero-terminated
1255              C strings
1256
1257 Returns:   growable string, changed if copied for expansion.
1258            The string is not zero-terminated - see string_cat() above.
1259 */
1260
1261 __inline__ gstring *
1262 string_append(gstring * g, int count, ...)
1263 {
1264 va_list ap;
1265
1266 va_start(ap, count);
1267 while (count-- > 0)
1268   {
1269   uschar * t = va_arg(ap, uschar *);
1270   g = string_cat(g, t);
1271   }
1272 va_end(ap);
1273
1274 return g;
1275 }
1276 #endif
1277
1278
1279
1280 /*************************************************
1281 *        Format a string with length checks      *
1282 *************************************************/
1283
1284 /* This function is used to format a string with checking of the length of the
1285 output for all conversions. It protects Exim from absent-mindedness when
1286 calling functions like debug_printf and string_sprintf, and elsewhere. There
1287 are two different entry points to what is actually the same function, depending
1288 on whether the variable length list of data arguments are given explicitly or
1289 as a va_list item.
1290
1291 The formats are the usual printf() ones, with some omissions (never used) and
1292 three additions for strings: %S forces lower case, %T forces upper case, and
1293 %#s or %#S prints nothing for a NULL string. Without the # "NULL" is printed
1294 (useful in debugging). There is also the addition of %D and %M, which insert
1295 the date in the form used for datestamped log files.
1296
1297 Arguments:
1298   buffer       a buffer in which to put the formatted string
1299   buflen       the length of the buffer
1300   format       the format string - deliberately char * and not uschar *
1301   ... or ap    variable list of supplementary arguments
1302
1303 Returns:       TRUE if the result fitted in the buffer
1304 */
1305
1306 BOOL
1307 string_format_trc(uschar * buffer, int buflen,
1308   const uschar * func, unsigned line, const char * format, ...)
1309 {
1310 gstring g = { .size = buflen, .ptr = 0, .s = buffer }, * gp;
1311 va_list ap;
1312 va_start(ap, format);
1313 gp = string_vformat_trc(&g, func, line, STRING_SPRINTF_BUFFER_SIZE,
1314         0, format, ap);
1315 va_end(ap);
1316 g.s[g.ptr] = '\0';
1317 return !!gp;
1318 }
1319
1320
1321
1322
1323 /* Build or append to a growing-string, sprintf-style.
1324
1325 Arguments:
1326         g       a growable-string
1327         func    called-from function name, for debug
1328         line    called-from file line number, for debug
1329         limit   maximum string size
1330         flags   see below
1331         format  printf-like format string
1332         ap      variable-args pointer
1333
1334 Flags:
1335         SVFMT_EXTEND            buffer can be created or exteded as needed
1336         SVFMT_REBUFFER          buffer can be recopied to tainted mem as needed
1337         SVFMT_TAINT_NOCHK       do not check inputs for taint
1338
1339 If the "extend" flag is true, the string passed in can be NULL,
1340 empty, or non-empty.  Growing is subject to an overall limit given
1341 by the limit argument.
1342
1343 If the "extend" flag is false, the string passed in may not be NULL,
1344 will not be grown, and is usable in the original place after return.
1345 The return value can be NULL to signify overflow.
1346
1347 Field width:            decimal digits, or *
1348 Precision:              dot, followed by decimal digits or *
1349 Length modifiers:       h  L  l  ll  z
1350 Conversion specifiers:  n d o u x X p f e E g G % c s S T Y D M
1351
1352 Returns the possibly-new (if copy for growth or taint-handling was needed)
1353 string, not nul-terminated.
1354 */
1355
1356 gstring *
1357 string_vformat_trc(gstring * g, const uschar * func, unsigned line,
1358   unsigned size_limit, unsigned flags, const char * format, va_list ap)
1359 {
1360 enum ltypes { L_NORMAL=1, L_SHORT=2, L_LONG=3, L_LONGLONG=4, L_LONGDOUBLE=5, L_SIZE=6 };
1361
1362 int width, precision, off, lim, need;
1363 const char * fp = format;       /* Deliberately not unsigned */
1364
1365 string_datestamp_offset = -1;   /* Datestamp not inserted */
1366 string_datestamp_length = 0;    /* Datestamp not inserted */
1367 string_datestamp_type = 0;      /* Datestamp not inserted */
1368
1369 #ifdef COMPILE_UTILITY
1370 assert(!(flags & SVFMT_EXTEND));
1371 assert(g);
1372 #else
1373
1374 /* Ensure we have a string, to save on checking later */
1375 if (!g) g = string_get(16);
1376
1377 if (!(flags & SVFMT_TAINT_NOCHK) && is_incompatible(g->s, format))
1378   {
1379 #ifndef MACRO_PREDEF
1380   if (!(flags & SVFMT_REBUFFER))
1381     die_tainted(US"string_vformat", func, line);
1382 #endif
1383 /* debug_printf("rebuf B\n"); */
1384   gstring_rebuffer(g, format);
1385   }
1386 #endif  /*!COMPILE_UTILITY*/
1387
1388 lim = g->size - 1;      /* leave one for a nul */
1389 off = g->ptr;           /* remember initial offset in gstring */
1390
1391 /* Scan the format and handle the insertions */
1392
1393 while (*fp)
1394   {
1395   int length = L_NORMAL;
1396   int * nptr;
1397   int slen;
1398   const char *null = "NULL";            /* ) These variables */
1399   const char *item_start, *s;           /* ) are deliberately */
1400   char newformat[16];                   /* ) not unsigned */
1401   char * gp = CS g->s + g->ptr;         /* ) */
1402
1403   /* Non-% characters just get copied verbatim */
1404
1405   if (*fp != '%')
1406     {
1407     /* Avoid string_copyn() due to COMPILE_UTILITY */
1408     if ((need = g->ptr + 1) > lim)
1409       {
1410       if (!(flags & SVFMT_EXTEND) || need > size_limit) return NULL;
1411       gstring_grow(g, 1);
1412       lim = g->size - 1;
1413       }
1414     g->s[g->ptr++] = (uschar) *fp++;
1415     continue;
1416     }
1417
1418   /* Deal with % characters. Pick off the width and precision, for checking
1419   strings, skipping over the flag and modifier characters. */
1420
1421   item_start = fp;
1422   width = precision = -1;
1423
1424   if (strchr("-+ #0", *(++fp)) != NULL)
1425     {
1426     if (*fp == '#') null = "";
1427     fp++;
1428     }
1429
1430   if (isdigit((uschar)*fp))
1431     {
1432     width = *fp++ - '0';
1433     while (isdigit((uschar)*fp)) width = width * 10 + *fp++ - '0';
1434     }
1435   else if (*fp == '*')
1436     {
1437     width = va_arg(ap, int);
1438     fp++;
1439     }
1440
1441   if (*fp == '.')
1442     if (*(++fp) == '*')
1443       {
1444       precision = va_arg(ap, int);
1445       fp++;
1446       }
1447     else
1448       for (precision = 0; isdigit((uschar)*fp); fp++)
1449         precision = precision*10 + *fp - '0';
1450
1451   /* Skip over 'h', 'L', 'l', 'll' and 'z', remembering the item length */
1452
1453   if (*fp == 'h')
1454     { fp++; length = L_SHORT; }
1455   else if (*fp == 'L')
1456     { fp++; length = L_LONGDOUBLE; }
1457   else if (*fp == 'l')
1458     if (fp[1] == 'l')
1459       { fp += 2; length = L_LONGLONG; }
1460     else
1461       { fp++; length = L_LONG; }
1462   else if (*fp == 'z')
1463     { fp++; length = L_SIZE; }
1464
1465   /* Handle each specific format type. */
1466
1467   switch (*fp++)
1468     {
1469     case 'n':
1470       nptr = va_arg(ap, int *);
1471       *nptr = g->ptr - off;
1472       break;
1473
1474     case 'd':
1475     case 'o':
1476     case 'u':
1477     case 'x':
1478     case 'X':
1479       width = length > L_LONG ? 24 : 12;
1480       if ((need = g->ptr + width) > lim)
1481         {
1482         if (!(flags & SVFMT_EXTEND) || need >= size_limit) return NULL;
1483         gstring_grow(g, width);
1484         lim = g->size - 1;
1485         gp = CS g->s + g->ptr;
1486         }
1487       strncpy(newformat, item_start, fp - item_start);
1488       newformat[fp - item_start] = 0;
1489
1490       /* Short int is promoted to int when passing through ..., so we must use
1491       int for va_arg(). */
1492
1493       switch(length)
1494         {
1495         case L_SHORT:
1496         case L_NORMAL:
1497           g->ptr += sprintf(gp, newformat, va_arg(ap, int)); break;
1498         case L_LONG:
1499           g->ptr += sprintf(gp, newformat, va_arg(ap, long int)); break;
1500         case L_LONGLONG:
1501           g->ptr += sprintf(gp, newformat, va_arg(ap, LONGLONG_T)); break;
1502         case L_SIZE:
1503           g->ptr += sprintf(gp, newformat, va_arg(ap, size_t)); break;
1504         }
1505       break;
1506
1507     case 'p':
1508       {
1509       void * ptr;
1510       if ((need = g->ptr + 24) > lim)
1511         {
1512         if (!(flags & SVFMT_EXTEND || need >= size_limit)) return NULL;
1513         gstring_grow(g, 24);
1514         lim = g->size - 1;
1515         gp = CS g->s + g->ptr;
1516         }
1517       /* sprintf() saying "(nil)" for a null pointer seems unreliable.
1518       Handle it explicitly. */
1519       if ((ptr = va_arg(ap, void *)))
1520         {
1521         strncpy(newformat, item_start, fp - item_start);
1522         newformat[fp - item_start] = 0;
1523         g->ptr += sprintf(gp, newformat, ptr);
1524         }
1525       else
1526         g->ptr += sprintf(gp, "(nil)");
1527       }
1528     break;
1529
1530     /* %f format is inherently insecure if the numbers that it may be
1531     handed are unknown (e.g. 1e300). However, in Exim, %f is used for
1532     printing load averages, and these are actually stored as integers
1533     (load average * 1000) so the size of the numbers is constrained.
1534     It is also used for formatting sending rates, where the simplicity
1535     of the format prevents overflow. */
1536
1537     case 'f':
1538     case 'e':
1539     case 'E':
1540     case 'g':
1541     case 'G':
1542       if (precision < 0) precision = 6;
1543       if ((need = g->ptr + precision + 8) > lim)
1544         {
1545         if (!(flags & SVFMT_EXTEND || need >= size_limit)) return NULL;
1546         gstring_grow(g, precision+8);
1547         lim = g->size - 1;
1548         gp = CS g->s + g->ptr;
1549         }
1550       strncpy(newformat, item_start, fp - item_start);
1551       newformat[fp-item_start] = 0;
1552       if (length == L_LONGDOUBLE)
1553         g->ptr += sprintf(gp, newformat, va_arg(ap, long double));
1554       else
1555         g->ptr += sprintf(gp, newformat, va_arg(ap, double));
1556       break;
1557
1558     /* String types */
1559
1560     case '%':
1561       if ((need = g->ptr + 1) > lim)
1562         {
1563         if (!(flags & SVFMT_EXTEND || need >= size_limit)) return NULL;
1564         gstring_grow(g, 1);
1565         lim = g->size - 1;
1566         }
1567       g->s[g->ptr++] = (uschar) '%';
1568       break;
1569
1570     case 'c':
1571       if ((need = g->ptr + 1) > lim)
1572         {
1573         if (!(flags & SVFMT_EXTEND || need >= size_limit)) return NULL;
1574         gstring_grow(g, 1);
1575         lim = g->size - 1;
1576         }
1577       g->s[g->ptr++] = (uschar) va_arg(ap, int);
1578       break;
1579
1580     case 'D':                   /* Insert daily datestamp for log file names */
1581       s = CS tod_stamp(tod_log_datestamp_daily);
1582       string_datestamp_offset = g->ptr;         /* Passed back via global */
1583       string_datestamp_length = Ustrlen(s);     /* Passed back via global */
1584       string_datestamp_type = tod_log_datestamp_daily;
1585       slen = string_datestamp_length;
1586       goto INSERT_STRING;
1587
1588     case 'M':                   /* Insert monthly datestamp for log file names */
1589       s = CS tod_stamp(tod_log_datestamp_monthly);
1590       string_datestamp_offset = g->ptr;         /* Passed back via global */
1591       string_datestamp_length = Ustrlen(s);     /* Passed back via global */
1592       string_datestamp_type = tod_log_datestamp_monthly;
1593       slen = string_datestamp_length;
1594       goto INSERT_STRING;
1595
1596     case 'Y':                   /* gstring pointer */
1597       {
1598       gstring * zg = va_arg(ap, gstring *);
1599       if (zg) { s = CS zg->s; slen = zg->ptr;    }
1600       else    { s = null;     slen = Ustrlen(s); }
1601       goto INSERT_GSTRING;
1602       }
1603
1604     case 's':
1605     case 'S':                   /* Forces *lower* case */
1606     case 'T':                   /* Forces *upper* case */
1607       s = va_arg(ap, char *);
1608
1609       if (!s) s = null;
1610       slen = Ustrlen(s);
1611
1612     INSERT_GSTRING:             /* Coome to from %Y above */
1613
1614       if (!(flags & SVFMT_TAINT_NOCHK) && is_incompatible(g->s, s))
1615         if (flags & SVFMT_REBUFFER)
1616           {
1617 /* debug_printf("%s %d: untainted workarea, tainted %%s :- rebuffer\n", __FUNCTION__, __LINE__); */
1618           gstring_rebuffer(g, s);
1619           gp = CS g->s + g->ptr;
1620           }
1621 #ifndef MACRO_PREDEF
1622         else
1623           die_tainted(US"string_vformat", func, line);
1624 #endif
1625
1626     INSERT_STRING:              /* Come to from %D or %M above */
1627
1628       {
1629       BOOL truncated = FALSE;
1630
1631       /* If the width is specified, check that there is a precision
1632       set; if not, set it to the width to prevent overruns of long
1633       strings. */
1634
1635       if (width >= 0)
1636         {
1637         if (precision < 0) precision = width;
1638         }
1639
1640       /* If a width is not specified and the precision is specified, set
1641       the width to the precision, or the string length if shorted. */
1642
1643       else if (precision >= 0)
1644         width = precision < slen ? precision : slen;
1645
1646       /* If neither are specified, set them both to the string length. */
1647
1648       else
1649         width = precision = slen;
1650
1651       if ((need = g->ptr + width) >= size_limit || !(flags & SVFMT_EXTEND))
1652         {
1653         if (g->ptr == lim) return NULL;
1654         if (need > lim)
1655           {
1656           truncated = TRUE;
1657           width = precision = lim - g->ptr - 1;
1658           if (width < 0) width = 0;
1659           if (precision < 0) precision = 0;
1660           }
1661         }
1662       else if (need > lim)
1663         {
1664         gstring_grow(g, width);
1665         lim = g->size - 1;
1666         gp = CS g->s + g->ptr;
1667         }
1668
1669       g->ptr += sprintf(gp, "%*.*s", width, precision, s);
1670       if (fp[-1] == 'S')
1671         while (*gp) { *gp = tolower(*gp); gp++; }
1672       else if (fp[-1] == 'T')
1673         while (*gp) { *gp = toupper(*gp); gp++; }
1674
1675       if (truncated) return NULL;
1676       break;
1677       }
1678
1679     /* Some things are never used in Exim; also catches junk. */
1680
1681     default:
1682       strncpy(newformat, item_start, fp - item_start);
1683       newformat[fp-item_start] = 0;
1684       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "string_format: unsupported type "
1685         "in \"%s\" in \"%s\"", newformat, format);
1686       break;
1687     }
1688   }
1689
1690 if (g->ptr > g->size)
1691   log_write(0, LOG_MAIN|LOG_PANIC_DIE,
1692     "string_format internal error: caller %s %d", func, line);
1693 return g;
1694 }
1695
1696
1697
1698 #ifndef COMPILE_UTILITY
1699 /*************************************************
1700 *       Generate an "open failed" message        *
1701 *************************************************/
1702
1703 /* This function creates a message after failure to open a file. It includes a
1704 string supplied as data, adds the strerror() text, and if the failure was
1705 "Permission denied", reads and includes the euid and egid.
1706
1707 Arguments:
1708   format        a text format string - deliberately not uschar *
1709   func          caller, for debug
1710   line          caller, for debug
1711   ...           arguments for the format string
1712
1713 Returns:        a message, in dynamic store
1714 */
1715
1716 uschar *
1717 string_open_failed_trc(const uschar * func, unsigned line,
1718   const char * format, ...)
1719 {
1720 va_list ap;
1721 gstring * g = string_get(1024);
1722
1723 g = string_catn(g, US"failed to open ", 15);
1724
1725 /* Use the checked formatting routine to ensure that the buffer
1726 does not overflow. It should not, since this is called only for internally
1727 specified messages. If it does, the message just gets truncated, and there
1728 doesn't seem much we can do about that. */
1729
1730 va_start(ap, format);
1731 (void) string_vformat_trc(g, func, line, STRING_SPRINTF_BUFFER_SIZE,
1732         SVFMT_REBUFFER, format, ap);
1733 va_end(ap);
1734
1735 g = string_catn(g, US": ", 2);
1736 g = string_cat(g, US strerror(errno));
1737
1738 if (errno == EACCES)
1739   {
1740   int save_errno = errno;
1741   g = string_fmt_append(g, " (euid=%ld egid=%ld)",
1742     (long int)geteuid(), (long int)getegid());
1743   errno = save_errno;
1744   }
1745 gstring_release_unused(g);
1746 return string_from_gstring(g);
1747 }
1748
1749
1750
1751
1752
1753 /* qsort(3), currently used to sort the environment variables
1754 for -bP environment output, needs a function to compare two pointers to string
1755 pointers. Here it is. */
1756
1757 int
1758 string_compare_by_pointer(const void *a, const void *b)
1759 {
1760 return Ustrcmp(* CUSS a, * CUSS b);
1761 }
1762 #endif /* COMPILE_UTILITY */
1763
1764
1765
1766
1767 /*************************************************
1768 **************************************************
1769 *             Stand-alone test program           *
1770 **************************************************
1771 *************************************************/
1772
1773 #ifdef STAND_ALONE
1774 int main(void)
1775 {
1776 uschar buffer[256];
1777
1778 printf("Testing is_ip_address\n");
1779 store_init();
1780
1781 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1782   {
1783   int offset;
1784   buffer[Ustrlen(buffer) - 1] = 0;
1785   printf("%d\n", string_is_ip_address(buffer, NULL));
1786   printf("%d %d %s\n", string_is_ip_address(buffer, &offset), offset, buffer);
1787   }
1788
1789 printf("Testing string_nextinlist\n");
1790
1791 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1792   {
1793   uschar *list = buffer;
1794   uschar *lp1, *lp2;
1795   uschar item[256];
1796   int sep1 = 0;
1797   int sep2 = 0;
1798
1799   if (*list == '<')
1800     {
1801     sep1 = sep2 = list[1];
1802     list += 2;
1803     }
1804
1805   lp1 = lp2 = list;
1806   for (;;)
1807     {
1808     uschar *item1 = string_nextinlist(&lp1, &sep1, item, sizeof(item));
1809     uschar *item2 = string_nextinlist(&lp2, &sep2, NULL, 0);
1810
1811     if (item1 == NULL && item2 == NULL) break;
1812     if (item == NULL || item2 == NULL || Ustrcmp(item1, item2) != 0)
1813       {
1814       printf("***ERROR\nitem1=\"%s\"\nitem2=\"%s\"\n",
1815         (item1 == NULL)? "NULL" : CS item1,
1816         (item2 == NULL)? "NULL" : CS item2);
1817       break;
1818       }
1819     else printf("  \"%s\"\n", CS item1);
1820     }
1821   }
1822
1823 /* This is a horrible lash-up, but it serves its purpose. */
1824
1825 printf("Testing string_format\n");
1826
1827 while (fgets(CS buffer, sizeof(buffer), stdin) != NULL)
1828   {
1829   void *args[3];
1830   long long llargs[3];
1831   double dargs[3];
1832   int dflag = 0;
1833   int llflag = 0;
1834   int n = 0;
1835   int count;
1836   BOOL countset = FASE;
1837   uschar format[256];
1838   uschar outbuf[256];
1839   uschar *s;
1840   buffer[Ustrlen(buffer) - 1] = 0;
1841
1842   s = Ustrchr(buffer, ',');
1843   if (s == NULL) s = buffer + Ustrlen(buffer);
1844
1845   Ustrncpy(format, buffer, s - buffer);
1846   format[s-buffer] = 0;
1847
1848   if (*s == ',') s++;
1849
1850   while (*s != 0)
1851     {
1852     uschar *ss = s;
1853     s = Ustrchr(ss, ',');
1854     if (s == NULL) s = ss + Ustrlen(ss);
1855
1856     if (isdigit(*ss))
1857       {
1858       Ustrncpy(outbuf, ss, s-ss);
1859       if (Ustrchr(outbuf, '.') != NULL)
1860         {
1861         dflag = 1;
1862         dargs[n++] = Ustrtod(outbuf, NULL);
1863         }
1864       else if (Ustrstr(outbuf, "ll") != NULL)
1865         {
1866         llflag = 1;
1867         llargs[n++] = strtoull(CS outbuf, NULL, 10);
1868         }
1869       else
1870         {
1871         args[n++] = (void *)Uatoi(outbuf);
1872         }
1873       }
1874
1875     else if (Ustrcmp(ss, "*") == 0)
1876       {
1877       args[n++] = (void *)(&count);
1878       countset = TRUE;
1879       }
1880
1881     else
1882       {
1883       uschar *sss = malloc(s - ss + 1);
1884       Ustrncpy(sss, ss, s-ss);
1885       args[n++] = sss;
1886       }
1887
1888     if (*s == ',') s++;
1889     }
1890
1891   if (!dflag && !llflag)
1892     printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1893       args[0], args[1], args[2])? "True" : "False");
1894
1895   else if (dflag)
1896     printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1897       dargs[0], dargs[1], dargs[2])? "True" : "False");
1898
1899   else printf("%s\n", string_format(outbuf, sizeof(outbuf), CS format,
1900     llargs[0], llargs[1], llargs[2])? "True" : "False");
1901
1902   printf("%s\n", CS outbuf);
1903   if (countset) printf("count=%d\n", count);
1904   }
1905
1906 return 0;
1907 }
1908 #endif
1909
1910 /* End of string.c */