Coverage Report

Created: 2024-06-18 06:24

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