tor  0.4.0.1-alpha
printf.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
11 #include "lib/string/printf.h"
12 #include "lib/err/torerr.h"
13 #include "lib/cc/torint.h"
14 #include "lib/malloc/malloc.h"
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 
26 int
27 tor_snprintf(char *str, size_t size, const char *format, ...)
28 {
29  va_list ap;
30  int r;
31  va_start(ap,format);
32  r = tor_vsnprintf(str,size,format,ap);
33  va_end(ap);
34  return r;
35 }
36 
40 int
41 tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
42 {
43  int r;
44  if (size == 0)
45  return -1; /* no place for the NUL */
46  if (size > SIZE_T_CEILING)
47  return -1;
48 #ifdef _WIN32
49  r = _vsnprintf(str, size, format, args);
50 #else
51  r = vsnprintf(str, size, format, args);
52 #endif
53  str[size-1] = '\0';
54  if (r < 0 || r >= (ssize_t)size)
55  return -1;
56  return r;
57 }
58 
74 int
75 tor_asprintf(char **strp, const char *fmt, ...)
76 {
77  int r;
78  va_list args;
79  va_start(args, fmt);
80  r = tor_vasprintf(strp, fmt, args);
81  va_end(args);
82  if (!*strp || r < 0) {
83  /* LCOV_EXCL_START */
84  raw_assert_unreached_msg("Internal error in asprintf");
85  /* LCOV_EXCL_STOP */
86  }
87  return r;
88 }
89 
95 int
96 tor_vasprintf(char **strp, const char *fmt, va_list args)
97 {
98  /* use a temporary variable in case *strp is in args. */
99  char *strp_tmp=NULL;
100 #ifdef HAVE_VASPRINTF
101  /* If the platform gives us one, use it. */
102  int r = vasprintf(&strp_tmp, fmt, args);
103  if (r < 0)
104  *strp = NULL; // LCOV_EXCL_LINE -- no cross-platform way to force this
105  else
106  *strp = strp_tmp;
107  return r;
108 #elif defined(HAVE__VSCPRINTF)
109  /* On Windows, _vsnprintf won't tell us the length of the string if it
110  * overflows, so we need to use _vcsprintf to tell how much to allocate */
111  int len, r;
112  va_list tmp_args;
113  va_copy(tmp_args, args);
114  len = _vscprintf(fmt, tmp_args);
115  va_end(tmp_args);
116  if (len < 0) {
117  *strp = NULL;
118  return -1;
119  }
120  strp_tmp = tor_malloc(len + 1);
121  r = _vsnprintf(strp_tmp, len+1, fmt, args);
122  if (r != len) {
123  tor_free(strp_tmp);
124  *strp = NULL;
125  return -1;
126  }
127  *strp = strp_tmp;
128  return len;
129 #else
130  /* Everywhere else, we have a decent vsnprintf that tells us how many
131  * characters we need. We give it a try on a short buffer first, since
132  * it might be nice to avoid the second vsnprintf call.
133  */
134  char buf[128];
135  int len, r;
136  va_list tmp_args;
137  va_copy(tmp_args, args);
138  /* vsnprintf() was properly checked but tor_vsnprintf() available so
139  * why not use it? */
140  len = tor_vsnprintf(buf, sizeof(buf), fmt, tmp_args);
141  va_end(tmp_args);
142  if (len < (int)sizeof(buf)) {
143  *strp = tor_strdup(buf);
144  return len;
145  }
146  strp_tmp = tor_malloc(len+1);
147  /* use of tor_vsnprintf() will ensure string is null terminated */
148  r = tor_vsnprintf(strp_tmp, len+1, fmt, args);
149  if (r != len) {
150  tor_free(strp_tmp);
151  *strp = NULL;
152  return -1;
153  }
154  *strp = strp_tmp;
155  return len;
156 #endif /* defined(HAVE_VASPRINTF) || ... */
157 }
Header for printf.c.
int tor_vasprintf(char **strp, const char *fmt, va_list args)
Definition: printf.c:96
#define tor_free(p)
Definition: malloc.h:52
Integer definitions used throughout Tor.
Headers for util_malloc.c.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
#define SIZE_T_CEILING
Definition: torint.h:126
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
Headers for torerr.c.
int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
Definition: printf.c:41