1 /*-------------------------------------------------------------------------
4 * sprintf into an allocated-on-demand buffer
7 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/common/psprintf.c
14 *-------------------------------------------------------------------------
21 #include "utils/memutils.h"
25 #include "postgres_fe.h"
33 * Format text data under the control of fmt (an sprintf-style format string)
34 * and return it in an allocated-on-demand buffer. The buffer is allocated
35 * with palloc in the backend, or malloc in frontend builds. Caller is
36 * responsible to free the buffer when no longer needed, if appropriate.
38 * Errors are not returned to the caller, but are reported via elog(ERROR)
39 * in the backend, or printf-to-stderr-and-exit() in frontend builds.
40 * One should therefore think twice about using this in libpq.
43 psprintf(const char *fmt
,...)
45 int save_errno
= errno
;
46 size_t len
= 128; /* initial assumption about buffer size */
55 * Allocate result buffer. Note that in frontend this maps to malloc
58 result
= (char *) palloc(len
);
60 /* Try to format the data. */
63 newlen
= pvsnprintf(result
, len
, fmt
, args
);
67 return result
; /* success */
69 /* Release buffer and loop around to try again with larger len. */
78 * Attempt to format text data under the control of fmt (an sprintf-style
79 * format string) and insert it into buf (which has length len).
81 * If successful, return the number of bytes emitted, not counting the
82 * trailing zero byte. This will always be strictly less than len.
84 * If there's not enough space in buf, return an estimate of the buffer size
85 * needed to succeed (this *must* be more than the given len, else callers
86 * might loop infinitely).
88 * Other error cases do not return, but exit via elog(ERROR) or exit().
89 * Hence, this shouldn't be used inside libpq.
91 * Caution: callers must be sure to preserve their entry-time errno
92 * when looping, in case the fmt contains "%m".
94 * Note that the semantics of the return value are not exactly C99's.
95 * First, we don't promise that the estimated buffer size is exactly right;
96 * callers must be prepared to loop multiple times to get the right size.
97 * (Given a C99-compliant vsnprintf, that won't happen, but it is rumored
98 * that some implementations don't always return the same value ...)
99 * Second, we return the recommended buffer size, not one less than that;
100 * this lets overflow concerns be handled here rather than in the callers.
103 pvsnprintf(char *buf
, size_t len
, const char *fmt
, va_list args
)
107 nprinted
= vsnprintf(buf
, len
, fmt
, args
);
109 /* We assume failure means the fmt is bogus, hence hard failure is OK */
110 if (unlikely(nprinted
< 0))
113 elog(ERROR
, "vsnprintf failed: %m with format string \"%s\"", fmt
);
115 fprintf(stderr
, "vsnprintf failed: %m with format string \"%s\"\n",
121 if ((size_t) nprinted
< len
)
123 /* Success. Note nprinted does not include trailing null. */
124 return (size_t) nprinted
;
128 * We assume a C99-compliant vsnprintf, so believe its estimate of the
129 * required space, and add one for the trailing null. (If it's wrong, the
130 * logic will still work, but we may loop multiple times.)
132 * Choke if the required space would exceed MaxAllocSize. Note we use
133 * this palloc-oriented overflow limit even when in frontend.
135 if (unlikely((size_t) nprinted
> MaxAllocSize
- 1))
139 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
140 errmsg("out of memory")));
142 fprintf(stderr
, _("out of memory\n"));