mutt stable branch with some hacks
1/*
2 * Copyright (C) 2010 Michael R. Elkins <me@mutt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <stdio.h>
20#include "lib.h"
21
22/* NOTE: Currently there is no check in configure.ac for vasprintf(3). the
23 * undefined behavior of the error condition makes it difficult to write a safe
24 * version using it.
25 */
26
27#ifdef HAVE_VASPRINTF
28int safe_asprintf (char **strp, const char *fmt, ...)
29{
30 va_list ap;
31 int n;
32
33 va_start (ap, fmt);
34 n = vasprintf (strp, fmt, ap);
35 va_end (ap);
36
37 /* GNU libc man page for vasprintf(3) states that the value of *strp
38 * is undefined when the return code is -1.
39 */
40 if (n < 0)
41 {
42 mutt_error _("Out of memory!");
43 sleep (1);
44 mutt_exit (1);
45 }
46
47 if (n == 0)
48 {
49 /* Mutt convention is to use NULL for 0-length strings */
50 FREE (strp); /* __FREE_CHECKED__ */
51 }
52
53 return n;
54}
55#else
56/* Allocate a C-string large enough to contain the formatted string.
57 * This is essentially malloc+sprintf in one.
58 */
59int safe_asprintf (char **strp, const char *fmt, ...)
60{
61 int rlen = STRING;
62 int n;
63
64 *strp = safe_malloc (rlen);
65 for (;;)
66 {
67 va_list ap;
68 va_start (ap, fmt);
69 n = vsnprintf (*strp, rlen, fmt, ap);
70 va_end (ap);
71 if (n < 0)
72 {
73 FREE (strp); /* __FREE_CHECKED__ */
74 return n;
75 }
76
77 if (n < rlen)
78 {
79 /* reduce space to just that which was used. note that 'n' does not
80 * include the terminal nul char.
81 */
82 if (n == 0) /* convention is to use NULL for zero-length strings. */
83 FREE (strp); /* __FREE_CHECKED__ */
84 else if (n != rlen - 1)
85 safe_realloc (strp, n + 1);
86 return n;
87 }
88 /* increase size and try again */
89 rlen = n + 1;
90 safe_realloc (strp, rlen);
91 }
92 /* not reached */
93}
94#endif /* HAVE_ASPRINTF */