Coverage Report

Created: 2024-05-20 01:00

/src/openiked-portable/compat/vis.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: vis.c,v 1.26 2022/05/04 18:57:50 deraadt 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
/* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32
33
#if !defined(HAVE_STRNVIS)
34
35
#include <sys/types.h>
36
#include <errno.h>
37
#include <ctype.h>
38
#include <limits.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <vis.h>
42
43
static int
44
isoctal(int c)
45
0
{
46
0
  u_char uc = c;
47
48
0
  return uc >= '0' && uc <= '7';
49
0
}
50
51
static int
52
isvisible(int c, int flag)
53
0
{
54
0
  int vis_sp = flag & VIS_SP;
55
0
  int vis_tab = flag & VIS_TAB;
56
0
  int vis_nl = flag & VIS_NL;
57
0
  int vis_safe = flag & VIS_SAFE;
58
0
  int vis_glob = flag & VIS_GLOB;
59
0
  int vis_all = flag & VIS_ALL;
60
0
  u_char uc = c;
61
62
0
  if (c == '\\' || !vis_all) {
63
0
    if ((u_int)c <= UCHAR_MAX && isascii(uc) &&
64
0
        ((c != '*' && c != '?' && c != '[' && c != '#') || !vis_glob) &&
65
0
        isgraph(uc))
66
0
      return 1;
67
0
    if (!vis_sp && c == ' ')
68
0
      return 1;
69
0
    if (!vis_tab && c == '\t')
70
0
      return 1;
71
0
    if (!vis_nl && c == '\n')
72
0
      return 1;
73
0
    if (vis_safe && (c == '\b' || c == '\007' || c == '\r' || isgraph(uc)))
74
0
      return 1;
75
0
  }
76
0
  return 0;
77
0
}
78
79
/*
80
 * vis - visually encode characters
81
 */
82
char *
83
vis(char *dst, int c, int flag, int nextc)
84
0
{
85
0
  int vis_dq = flag & VIS_DQ;
86
0
  int vis_noslash = flag & VIS_NOSLASH;
87
0
  int vis_cstyle = flag & VIS_CSTYLE;
88
0
  int vis_octal = flag & VIS_OCTAL;
89
0
  int vis_glob = flag & VIS_GLOB;
90
91
0
  if (isvisible(c, flag)) {
92
0
    if ((c == '"' && vis_dq) ||
93
0
        (c == '\\' && !vis_noslash))
94
0
      *dst++ = '\\';
95
0
    *dst++ = c;
96
0
    *dst = '\0';
97
0
    return (dst);
98
0
  }
99
100
0
  if (vis_cstyle) {
101
0
    switch (c) {
102
0
    case '\n':
103
0
      *dst++ = '\\';
104
0
      *dst++ = 'n';
105
0
      goto done;
106
0
    case '\r':
107
0
      *dst++ = '\\';
108
0
      *dst++ = 'r';
109
0
      goto done;
110
0
    case '\b':
111
0
      *dst++ = '\\';
112
0
      *dst++ = 'b';
113
0
      goto done;
114
0
    case '\a':
115
0
      *dst++ = '\\';
116
0
      *dst++ = 'a';
117
0
      goto done;
118
0
    case '\v':
119
0
      *dst++ = '\\';
120
0
      *dst++ = 'v';
121
0
      goto done;
122
0
    case '\t':
123
0
      *dst++ = '\\';
124
0
      *dst++ = 't';
125
0
      goto done;
126
0
    case '\f':
127
0
      *dst++ = '\\';
128
0
      *dst++ = 'f';
129
0
      goto done;
130
0
    case ' ':
131
0
      *dst++ = '\\';
132
0
      *dst++ = 's';
133
0
      goto done;
134
0
    case '\0':
135
0
      *dst++ = '\\';
136
0
      *dst++ = '0';
137
0
      if (isoctal(nextc)) {
138
0
        *dst++ = '0';
139
0
        *dst++ = '0';
140
0
      }
141
0
      goto done;
142
0
    }
143
0
  }
144
0
  if (((c & 0177) == ' ') || vis_octal ||
145
0
      (vis_glob && (c == '*' || c == '?' || c == '[' || c == '#'))) {
146
0
    *dst++ = '\\';
147
0
    *dst++ = ((u_char)c >> 6 & 07) + '0';
148
0
    *dst++ = ((u_char)c >> 3 & 07) + '0';
149
0
    *dst++ = ((u_char)c & 07) + '0';
150
0
    goto done;
151
0
  }
152
0
  if (!vis_noslash)
153
0
    *dst++ = '\\';
154
0
  if (c & 0200) {
155
0
    c &= 0177;
156
0
    *dst++ = 'M';
157
0
  }
158
0
  if (iscntrl((u_char)c)) {
159
0
    *dst++ = '^';
160
0
    if (c == 0177)
161
0
      *dst++ = '?';
162
0
    else
163
0
      *dst++ = c + '@';
164
0
  } else {
165
0
    *dst++ = '-';
166
0
    *dst++ = c;
167
0
  }
168
0
done:
169
0
  *dst = '\0';
170
0
  return (dst);
171
0
}
172
173
/*
174
 * strvis, strnvis, strvisx - visually encode characters from src into dst
175
 *  
176
 *  Dst must be 4 times the size of src to account for possible
177
 *  expansion.  The length of dst, not including the trailing NULL,
178
 *  is returned. 
179
 *
180
 *  Strnvis will write no more than siz-1 bytes (and will NULL terminate).
181
 *  The number of bytes needed to fully encode the string is returned.
182
 *
183
 *  Strvisx encodes exactly len bytes from src into dst.
184
 *  This is useful for encoding a block of data.
185
 */
186
int
187
strvis(char *dst, const char *src, int flag)
188
0
{
189
0
  char c;
190
0
  char *start;
191
192
0
  for (start = dst; (c = *src);)
193
0
    dst = vis(dst, c, flag, *++src);
194
0
  *dst = '\0';
195
0
  return (dst - start);
196
0
}
197
198
int
199
strnvis(char *dst, const char *src, size_t siz, int flag)
200
0
{
201
0
  int vis_dq = flag & VIS_DQ;
202
0
  int vis_noslash = flag & VIS_NOSLASH;
203
0
  char *start, *end;
204
0
  char tbuf[5];
205
0
  int c, i;
206
207
0
  i = 0;
208
0
  for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
209
0
    if (isvisible(c, flag)) {
210
0
      if ((c == '"' && vis_dq) ||
211
0
          (c == '\\' && !vis_noslash)) {
212
        /* need space for the extra '\\' */
213
0
        if (dst + 1 >= end) {
214
0
          i = 2;
215
0
          break;
216
0
        }
217
0
        *dst++ = '\\';
218
0
      }
219
0
      i = 1;
220
0
      *dst++ = c;
221
0
      src++;
222
0
    } else {
223
0
      i = vis(tbuf, c, flag, *++src) - tbuf;
224
0
      if (dst + i <= end) {
225
0
        memcpy(dst, tbuf, i);
226
0
        dst += i;
227
0
      } else {
228
0
        src--;
229
0
        break;
230
0
      }
231
0
    }
232
0
  }
233
0
  if (siz > 0)
234
0
    *dst = '\0';
235
0
  if (dst + i > end) {
236
    /* adjust return value for truncation */
237
0
    while ((c = *src))
238
0
      dst += vis(tbuf, c, flag, *++src) - tbuf;
239
0
  }
240
0
  return (dst - start);
241
0
}
242
243
int
244
stravis(char **outp, const char *src, int flag)
245
0
{
246
0
  char *buf;
247
0
  int len, serrno;
248
249
0
  buf = reallocarray(NULL, 4, strlen(src) + 1);
250
0
  if (buf == NULL)
251
0
    return -1;
252
0
  len = strvis(buf, src, flag);
253
0
  serrno = errno;
254
0
  *outp = realloc(buf, len + 1);
255
0
  if (*outp == NULL) {
256
0
    *outp = buf;
257
0
    errno = serrno;
258
0
  }
259
0
  return (len);
260
0
}
261
262
int
263
strvisx(char *dst, const char *src, size_t len, int flag)
264
0
{
265
0
  char c;
266
0
  char *start;
267
268
0
  for (start = dst; len > 1; len--) {
269
0
    c = *src;
270
0
    dst = vis(dst, c, flag, *++src);
271
0
  }
272
0
  if (len)
273
0
    dst = vis(dst, *src, flag, '\0');
274
0
  *dst = '\0';
275
0
  return (dst - start);
276
0
}
277
278
#endif