GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcurses/base/safe_sprintf.c Lines: 0 17 0.0 %
Date: 2016-12-06 Branches: 0 14 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: safe_sprintf.c,v 1.6 2010/10/18 18:22:35 nicm Exp $ */
2
3
/****************************************************************************
4
 * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc.              *
5
 *                                                                          *
6
 * Permission is hereby granted, free of charge, to any person obtaining a  *
7
 * copy of this software and associated documentation files (the            *
8
 * "Software"), to deal in the Software without restriction, including      *
9
 * without limitation the rights to use, copy, modify, merge, publish,      *
10
 * distribute, distribute with modifications, sublicense, and/or sell       *
11
 * copies of the Software, and to permit persons to whom the Software is    *
12
 * furnished to do so, subject to the following conditions:                 *
13
 *                                                                          *
14
 * The above copyright notice and this permission notice shall be included  *
15
 * in all copies or substantial portions of the Software.                   *
16
 *                                                                          *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
20
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
21
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
22
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
23
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
24
 *                                                                          *
25
 * Except as contained in this notice, the name(s) of the above copyright   *
26
 * holders shall not be used in advertising or otherwise to promote the     *
27
 * sale, use or other dealings in this Software without prior written       *
28
 * authorization.                                                           *
29
 ****************************************************************************/
30
31
/****************************************************************************
32
 *  Author: Thomas E. Dickey <dickey@clark.net> 1997                        *
33
 ****************************************************************************/
34
35
#include <curses.priv.h>
36
#include <ctype.h>
37
38
MODULE_ID("$Id: safe_sprintf.c,v 1.6 2010/10/18 18:22:35 nicm Exp $")
39
40
#if USE_SAFE_SPRINTF
41
42
typedef enum {
43
    Flags, Width, Prec, Type, Format
44
} PRINTF;
45
46
#define VA_INTGR(type) ival = va_arg(ap, type)
47
#define VA_FLOAT(type) fval = va_arg(ap, type)
48
#define VA_POINT(type) pval = (void *)va_arg(ap, type)
49
50
/*
51
 * Scan a variable-argument list for printf to determine the number of
52
 * characters that would be emitted.
53
 */
54
static int
55
_nc_printf_length(const char *fmt, va_list ap)
56
{
57
    size_t length = BUFSIZ;
58
    char *buffer;
59
    char *format;
60
    char *tmp_format;
61
    int len = 0;
62
    size_t fmt_len;
63
    char fmt_arg[BUFSIZ];
64
65
    if (fmt == 0 || *fmt == '\0')
66
	return 0;
67
    fmt_len = strlen(fmt) + 1;
68
    if ((format = typeMalloc(char, fmt_len)) == 0)
69
	  return -1;
70
    if ((buffer = typeMalloc(char, length)) == 0) {
71
	free(format);
72
	return -1;
73
    }
74
75
    while (*fmt != '\0') {
76
	if (*fmt == '%') {
77
	    static char dummy[] = "";
78
	    PRINTF state = Flags;
79
	    char *pval = dummy;	/* avoid const-cast */
80
	    double fval = 0.0;
81
	    int done = FALSE;
82
	    int ival = 0;
83
	    int prec = -1;
84
	    int type = 0;
85
	    int used = 0;
86
	    int width = -1;
87
	    size_t f = 0;
88
89
	    format[f++] = *fmt;
90
	    while (*++fmt != '\0' && len >= 0 && !done) {
91
		format[f++] = *fmt;
92
93
		if (isdigit(UChar(*fmt))) {
94
		    int num = *fmt - '0';
95
		    if (state == Flags && num != 0)
96
			state = Width;
97
		    if (state == Width) {
98
			if (width < 0)
99
			    width = 0;
100
			width = (width * 10) + num;
101
		    } else if (state == Prec) {
102
			if (prec < 0)
103
			    prec = 0;
104
			prec = (prec * 10) + num;
105
		    }
106
		} else if (*fmt == '*') {
107
		    VA_INTGR(int);
108
		    if (state == Flags)
109
			state = Width;
110
		    if (state == Width) {
111
			width = ival;
112
		    } else if (state == Prec) {
113
			prec = ival;
114
		    }
115
		    sprintf(fmt_arg, "%d", ival);
116
		    fmt_len += strlen(fmt_arg);
117
		    if ((tmp_format = realloc(format, fmt_len)) == 0) {
118
			free(buffer);
119
			free(format);
120
			return -1;
121
		    }
122
		    format = tmp_format;
123
		    strcpy(&format[--f], fmt_arg);
124
		    f = strlen(format);
125
		} else if (isalpha(UChar(*fmt))) {
126
		    done = TRUE;
127
		    switch (*fmt) {
128
		    case 'Z':	/* FALLTHRU */
129
		    case 'h':	/* FALLTHRU */
130
		    case 'l':	/* FALLTHRU */
131
			done = FALSE;
132
			type = *fmt;
133
			break;
134
		    case 'i':	/* FALLTHRU */
135
		    case 'd':	/* FALLTHRU */
136
		    case 'u':	/* FALLTHRU */
137
		    case 'x':	/* FALLTHRU */
138
		    case 'X':	/* FALLTHRU */
139
			if (type == 'l')
140
			    VA_INTGR(long);
141
			else if (type == 'Z')
142
			    VA_INTGR(size_t);
143
			else
144
			    VA_INTGR(int);
145
			used = 'i';
146
			break;
147
		    case 'f':	/* FALLTHRU */
148
		    case 'e':	/* FALLTHRU */
149
		    case 'E':	/* FALLTHRU */
150
		    case 'g':	/* FALLTHRU */
151
		    case 'G':	/* FALLTHRU */
152
			VA_FLOAT(double);
153
			used = 'f';
154
			break;
155
		    case 'c':
156
			VA_INTGR(int);
157
			used = 'i';
158
			break;
159
		    case 's':
160
			VA_POINT(char *);
161
			if (prec < 0)
162
			    prec = strlen(pval);
163
			if (prec > (int) length) {
164
			    length = length + prec;
165
			    buffer = typeRealloc(char, length, buffer);
166
			    if (buffer == 0) {
167
				free(format);
168
				return -1;
169
			    }
170
			}
171
			used = 'p';
172
			break;
173
		    case 'p':
174
			VA_POINT(void *);
175
			used = 'p';
176
			break;
177
		    case 'n':
178
			VA_POINT(int *);
179
			used = 0;
180
			break;
181
		    default:
182
			break;
183
		    }
184
		} else if (*fmt == '.') {
185
		    state = Prec;
186
		} else if (*fmt == '%') {
187
		    done = TRUE;
188
		    used = 'p';
189
		}
190
	    }
191
	    format[f] = '\0';
192
	    switch (used) {
193
	    case 'i':
194
		sprintf(buffer, format, ival);
195
		break;
196
	    case 'f':
197
		sprintf(buffer, format, fval);
198
		break;
199
	    default:
200
		sprintf(buffer, format, pval);
201
		break;
202
	    }
203
	    len += (int) strlen(buffer);
204
	} else {
205
	    fmt++;
206
	    len++;
207
	}
208
    }
209
210
    free(buffer);
211
    free(format);
212
    return len;
213
}
214
#endif
215
216
#define my_buffer _nc_globals.safeprint_buf
217
#define my_length _nc_globals.safeprint_used
218
219
/*
220
 * Wrapper for vsprintf that allocates a buffer big enough to hold the result.
221
 */
222
NCURSES_EXPORT(char *)
223
_nc_printf_string(const char *fmt, va_list ap)
224
{
225
    char *result = 0;
226
227
    if (fmt != 0) {
228
#if USE_SAFE_SPRINTF
229
	int len = _nc_printf_length(fmt, ap);
230
231
	if ((int) my_length < len + 1) {
232
	    my_length = 2 * (len + 1);
233
	    my_buffer = typeRealloc(char, my_length, my_buffer);
234
	}
235
	if (my_buffer != 0) {
236
	    *my_buffer = '\0';
237
	    if (len >= 0) {
238
		vsprintf(my_buffer, fmt, ap);
239
	    }
240
	    result = my_buffer;
241
	}
242
#else
243
#define MyCols _nc_globals.safeprint_cols
244
#define MyRows _nc_globals.safeprint_rows
245
246
	if (screen_lines > MyRows || screen_columns > MyCols) {
247
	    if (screen_lines > MyRows)
248
		MyRows = screen_lines;
249
	    if (screen_columns > MyCols)
250
		MyCols = screen_columns;
251
	    my_length = (MyRows * (MyCols + 1)) + 1;
252
	    my_buffer = typeRealloc(char, my_length, my_buffer);
253
	}
254
255
	if (my_buffer != 0) {
256
# if HAVE_VSNPRINTF
257
	    vsnprintf(my_buffer, my_length, fmt, ap);	/* GNU extension */
258
# else
259
	    vsprintf(my_buffer, fmt, ap);	/* ANSI */
260
# endif
261
	    result = my_buffer;
262
	}
263
#endif
264
    } else if (my_buffer != 0) {	/* see _nc_freeall() */
265
	free(my_buffer);
266
	my_buffer = 0;
267
	my_length = 0;
268
    }
269
    return result;
270
}