GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/gen/vis.c Lines: 77 105 73.3 %
Date: 2017-11-07 Branches: 58 124 46.8 %

Line Branch Exec Source
1
/*	$OpenBSD: vis.c,v 1.25 2015/09/13 11:32:51 guenther Exp $ */
2
/*-
3
 * Copyright (c) 1989, 1993
4
 *	The Regents of the University of California.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include <sys/types.h>
32
#include <errno.h>
33
#include <ctype.h>
34
#include <limits.h>
35
#include <string.h>
36
#include <stdlib.h>
37
#include <vis.h>
38
39
#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
40
#define	isvisible(c,flag)						\
41
	(((c) == '\\' || (flag & VIS_ALL) == 0) &&			\
42
	(((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) &&		\
43
	(((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') ||	\
44
		(flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) ||	\
45
	((flag & VIS_SP) == 0 && (c) == ' ') ||				\
46
	((flag & VIS_TAB) == 0 && (c) == '\t') ||			\
47
	((flag & VIS_NL) == 0 && (c) == '\n') ||			\
48
	((flag & VIS_SAFE) && ((c) == '\b' ||				\
49
		(c) == '\007' || (c) == '\r' ||				\
50
		isgraph((u_char)(c))))))
51
52
/*
53
 * vis - visually encode characters
54
 */
55
char *
56
vis(char *dst, int c, int flag, int nextc)
57
{
58






389798027
	if (isvisible(c, flag)) {
59

38380723
		if ((c == '"' && (flag & VIS_DQ) != 0) ||
60
38355943
		    (c == '\\' && (flag & VIS_NOSLASH) == 0))
61
13784
			*dst++ = '\\';
62
38342159
		*dst++ = c;
63
38342159
		*dst = '\0';
64
38342159
		return (dst);
65
	}
66
67
11449278
	if (flag & VIS_CSTYLE) {
68


11449278
		switch(c) {
69
		case '\n':
70
10
			*dst++ = '\\';
71
10
			*dst++ = 'n';
72
10
			goto done;
73
		case '\r':
74
15074
			*dst++ = '\\';
75
15074
			*dst++ = 'r';
76
15074
			goto done;
77
		case '\b':
78
35190
			*dst++ = '\\';
79
35190
			*dst++ = 'b';
80
35190
			goto done;
81
		case '\a':
82
21777
			*dst++ = '\\';
83
21777
			*dst++ = 'a';
84
21777
			goto done;
85
		case '\v':
86
20037
			*dst++ = '\\';
87
20037
			*dst++ = 'v';
88
20037
			goto done;
89
		case '\t':
90
10
			*dst++ = '\\';
91
10
			*dst++ = 't';
92
10
			goto done;
93
		case '\f':
94
18181
			*dst++ = '\\';
95
18181
			*dst++ = 'f';
96
18181
			goto done;
97
		case ' ':
98
			*dst++ = '\\';
99
			*dst++ = 's';
100
			goto done;
101
		case '\0':
102
7199215
			*dst++ = '\\';
103
7199215
			*dst++ = '0';
104

7908275
			if (isoctal(nextc)) {
105
38867
				*dst++ = '0';
106
38867
				*dst++ = '0';
107
38867
			}
108
			goto done;
109
		}
110
	}
111

8241412
	if (((c & 0177) == ' ') || (flag & VIS_OCTAL) ||
112

4101628
	    ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) {
113
38156
		*dst++ = '\\';
114
38156
		*dst++ = ((u_char)c >> 6 & 07) + '0';
115
38156
		*dst++ = ((u_char)c >> 3 & 07) + '0';
116
38156
		*dst++ = ((u_char)c & 07) + '0';
117
38156
		goto done;
118
	}
119
4101628
	if ((flag & VIS_NOSLASH) == 0)
120
4101628
		*dst++ = '\\';
121
4101628
	if (c & 0200) {
122
		c &= 0177;
123
3491867
		*dst++ = 'M';
124
3491867
	}
125
4101628
	if (iscntrl((u_char)c)) {
126
2946697
		*dst++ = '^';
127
2946697
		if (c == 0177)
128
1950476
			*dst++ = '?';
129
		else
130
996221
			*dst++ = c + '@';
131
	} else {
132
1154931
		*dst++ = '-';
133
1154931
		*dst++ = c;
134
	}
135
done:
136
11449278
	*dst = '\0';
137
11449278
	return (dst);
138
49791437
}
139
DEF_WEAK(vis);
140
141
/*
142
 * strvis, strnvis, strvisx - visually encode characters from src into dst
143
 *
144
 *	Dst must be 4 times the size of src to account for possible
145
 *	expansion.  The length of dst, not including the trailing NULL,
146
 *	is returned.
147
 *
148
 *	Strnvis will write no more than siz-1 bytes (and will NULL terminate).
149
 *	The number of bytes needed to fully encode the string is returned.
150
 *
151
 *	Strvisx encodes exactly len bytes from src into dst.
152
 *	This is useful for encoding a block of data.
153
 */
154
int
155
strvis(char *dst, const char *src, int flag)
156
{
157
	char c;
158
	char *start;
159
160
35450
	for (start = dst; (c = *src);)
161
15730
		dst = vis(dst, c, flag, *++src);
162
1330
	*dst = '\0';
163
1330
	return (dst - start);
164
}
165
DEF_WEAK(strvis);
166
167
int
168
strnvis(char *dst, const char *src, size_t siz, int flag)
169
{
170
	char *start, *end;
171
	char tbuf[5];
172
	int c, i;
173
174
	i = 0;
175
	for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
176
		if (isvisible(c, flag)) {
177
			if ((c == '"' && (flag & VIS_DQ) != 0) ||
178
			    (c == '\\' && (flag & VIS_NOSLASH) == 0)) {
179
				/* need space for the extra '\\' */
180
				if (dst + 1 >= end) {
181
					i = 2;
182
					break;
183
				}
184
				*dst++ = '\\';
185
			}
186
			i = 1;
187
			*dst++ = c;
188
			src++;
189
		} else {
190
			i = vis(tbuf, c, flag, *++src) - tbuf;
191
			if (dst + i <= end) {
192
				memcpy(dst, tbuf, i);
193
				dst += i;
194
			} else {
195
				src--;
196
				break;
197
			}
198
		}
199
	}
200
	if (siz > 0)
201
		*dst = '\0';
202
	if (dst + i > end) {
203
		/* adjust return value for truncation */
204
		while ((c = *src))
205
			dst += vis(tbuf, c, flag, *++src) - tbuf;
206
	}
207
	return (dst - start);
208
}
209
210
int
211
stravis(char **outp, const char *src, int flag)
212
{
213
	char *buf;
214
	int len, serrno;
215
216
2660
	buf = reallocarray(NULL, 4, strlen(src) + 1);
217
1330
	if (buf == NULL)
218
		return -1;
219
1330
	len = strvis(buf, src, flag);
220
1330
	serrno = errno;
221
1330
	*outp = realloc(buf, len + 1);
222
1330
	if (*outp == NULL) {
223
		*outp = buf;
224
		errno = serrno;
225
	}
226
1330
	return (len);
227
1330
}
228
229
int
230
strvisx(char *dst, const char *src, size_t len, int flag)
231
{
232
	char c;
233
	char *start;
234
235
4703
	for (start = dst; len > 1; len--) {
236
1708
		c = *src;
237
1708
		dst = vis(dst, c, flag, *++src);
238
	}
239
429
	if (len)
240
244
		dst = vis(dst, *src, flag, '\0');
241
429
	*dst = '\0';
242
429
	return (dst - start);
243
}