1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-26 07:55:01 +00:00

Merge commit 'acb089b983171667467adc66f56a723b609ed22e' into kbsd/vis

Highlights:
- Some style fixes
- Bumped mbbuf in istrsenvisx() to MB_LEN_MAX to avoid VLAs
- mbslength cannot go negative, so make it unsigned
- Further bounds checking & fix an additional overrun, with dlen == 0
- Avoid duplicate call to wcslen(start)
This commit is contained in:
Kyle Evans 2023-08-13 00:23:02 -05:00
commit ea46e63863
5 changed files with 76 additions and 30 deletions

View File

@ -1,5 +1,4 @@
.\" $NetBSD: unvis.3,v 1.29 2017/10/24 19:14:55 abhinav Exp $ .\" $NetBSD: unvis.3,v 1.30 2019/05/08 15:37:41 bad Exp $
.\" $FreeBSD$
.\" .\"
.\" Copyright (c) 1989, 1991, 1993 .\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -30,7 +29,7 @@
.\" .\"
.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93 .\" @(#)unvis.3 8.2 (Berkeley) 12/11/93
.\" .\"
.Dd March 12, 2011 .Dd May 8, 2019
.Dt UNVIS 3 .Dt UNVIS 3
.Os .Os
.Sh NAME .Sh NAME
@ -100,16 +99,18 @@ should be equal to the size of
.Pp .Pp
The The
.Fn strunvisx .Fn strunvisx
function does the same as the and
.Fn strnunvisx
functions do the same as the
.Fn strunvis .Fn strunvis
function, and
but it allows you to add a flag that specifies the style the string .Fn strnunvis
functions,
but take a flag that specifies the style the string
.Ar src .Ar src
is encoded with. is encoded with.
Currently, the supported flags are: The meaning of the flag is the same as explained below for
.Dv VIS_HTTPSTYLE .Fn unvis .
and
.Dv VIS_MIMESTYLE .
.Pp .Pp
The The
.Fn unvis .Fn unvis
@ -158,6 +159,10 @@ The
.Fa flag .Fa flag
argument is also used to specify the encoding style of the source. argument is also used to specify the encoding style of the source.
If set to If set to
.Dv VIS_NOESCAPE
.Fn unvis
will not decode backslash escapes.
If set to
.Dv VIS_HTTPSTYLE .Dv VIS_HTTPSTYLE
or or
.Dv VIS_HTTP1808 , .Dv VIS_HTTP1808 ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: unvis.c,v 1.44 2014/09/26 15:43:36 roy Exp $ */ /* $NetBSD: unvis.c,v 1.45 2022/04/19 20:32:15 rillig Exp $ */
/*- /*-
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
@ -34,7 +34,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
#else #else
__RCSID("$NetBSD: unvis.c,v 1.44 2014/09/26 15:43:36 roy Exp $"); __RCSID("$NetBSD: unvis.c,v 1.45 2022/04/19 20:32:15 rillig Exp $");
#endif #endif
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
@ -514,7 +514,7 @@ strnunvisx(char *dst, size_t dlen, const char *src, int flag)
errno = ENOSPC; \ errno = ENOSPC; \
return -1; \ return -1; \
} \ } \
} while (/*CONSTCOND*/0) } while (0)
while ((c = *src++) != '\0') { while ((c = *src++) != '\0') {
again: again:

View File

@ -1,5 +1,4 @@
.\" $NetBSD: vis.3,v 1.49 2017/08/05 20:22:29 wiz Exp $ .\" $NetBSD: vis.3,v 1.50 2022/12/04 11:25:08 uwe Exp $
.\" $FreeBSD$
.\" .\"
.\" Copyright (c) 1989, 1991, 1993 .\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -180,7 +179,7 @@ and
functions return \-1 and set functions return \-1 and set
.Va errno .Va errno
to to
.Dv ENOSPC . .Er ENOSPC .
The The
.Fn strenvisx .Fn strenvisx
function takes an additional argument, function takes an additional argument,

View File

@ -1,4 +1,4 @@
/* $NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $ */ /* $NetBSD: vis.c,v 1.83 2023/08/12 12:48:52 riastradh Exp $ */
/*- /*-
* Copyright (c) 1989, 1993 * Copyright (c) 1989, 1993
@ -57,7 +57,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $"); __RCSID("$NetBSD: vis.c,v 1.83 2023/08/12 12:48:52 riastradh Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#ifdef __FBSDID #ifdef __FBSDID
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
@ -360,7 +360,9 @@ makeextralist(int flags, const char *src)
if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
return NULL; return NULL;
if ((flags & VIS_NOLOCALE) || mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) { memset(&mbstate, 0, sizeof(mbstate));
if ((flags & VIS_NOLOCALE)
|| mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) {
size_t i; size_t i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
dst[i] = (wchar_t)(u_char)src[i]; dst[i] = (wchar_t)(u_char)src[i];
@ -395,7 +397,7 @@ static int
istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
int flags, const char *mbextra, int *cerr_ptr) int flags, const char *mbextra, int *cerr_ptr)
{ {
char mbbuf[MB_CUR_MAX]; char mbbuf[MB_LEN_MAX];
wchar_t *dst, *src, *pdst, *psrc, *start, *extra; wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
size_t len, olen; size_t len, olen;
uint64_t bmsk, wmsk; uint64_t bmsk, wmsk;
@ -403,7 +405,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
visfun_t f; visfun_t f;
int clen = 0, cerr, error = -1, i, shft; int clen = 0, cerr, error = -1, i, shft;
char *mbdst, *mbwrite, *mdst; char *mbdst, *mbwrite, *mdst;
ssize_t mbslength; size_t mbslength;
size_t maxolen; size_t maxolen;
mbstate_t mbstate; mbstate_t mbstate;
@ -411,7 +413,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
_DIAGASSERT(mbsrc != NULL || mblength == 0); _DIAGASSERT(mbsrc != NULL || mblength == 0);
_DIAGASSERT(mbextra != NULL); _DIAGASSERT(mbextra != NULL);
mbslength = (ssize_t)mblength; mbslength = mblength;
/* /*
* When inputing a single character, must also read in the * When inputing a single character, must also read in the
* next character for nextc, the look-ahead character. * next character for nextc, the look-ahead character.
@ -432,6 +434,14 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
* return to the caller. * return to the caller.
*/ */
/*
* Guarantee the arithmetic on input to calloc won't overflow.
*/
if (mbslength > (SIZE_MAX - 1)/16) {
errno = ENOMEM;
return -1;
}
/* Allocate space for the wide char strings */ /* Allocate space for the wide char strings */
psrc = pdst = extra = NULL; psrc = pdst = extra = NULL;
mdst = NULL; mdst = NULL;
@ -463,12 +473,18 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
* stop at NULs because we may be processing a block of data * stop at NULs because we may be processing a block of data
* that includes NULs. * that includes NULs.
*/ */
bzero(&mbstate, sizeof(mbstate)); memset(&mbstate, 0, sizeof(mbstate));
while (mbslength > 0) { while (mbslength > 0) {
/* Convert one multibyte character to wchar_t. */ /* Convert one multibyte character to wchar_t. */
if (!cerr) if (!cerr) {
clen = mbrtowc(src, mbsrc, MIN(mbslength, MB_LEN_MAX), clen = mbrtowc(src, mbsrc,
(mbslength < MB_LEN_MAX
? mbslength
: MB_LEN_MAX),
&mbstate); &mbstate);
assert(clen < 0 || (size_t)clen <= mbslength);
assert(clen <= MB_LEN_MAX);
}
if (cerr || clen < 0) { if (cerr || clen < 0) {
/* Conversion error, process as a byte instead. */ /* Conversion error, process as a byte instead. */
*src = (wint_t)(u_char)*mbsrc; *src = (wint_t)(u_char)*mbsrc;
@ -482,6 +498,20 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
*/ */
clen = 1; clen = 1;
} }
/*
* Let n := MIN(mbslength, MB_LEN_MAX). We have:
*
* mbslength >= 1
* mbrtowc(..., n, &mbstate) <= n,
* by the contract of mbrtowc
*
* clen is either
* (a) mbrtowc(..., n, &mbstate), in which case
* clen <= n <= mbslength; or
* (b) 1, in which case clen = 1 <= mbslength.
*/
assert(clen > 0);
assert((size_t)clen <= mbslength);
/* Advance buffer character pointer. */ /* Advance buffer character pointer. */
src++; src++;
/* Advance input pointer by number of bytes read. */ /* Advance input pointer by number of bytes read. */
@ -539,9 +569,21 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
* output byte-by-byte here. Else use wctomb(). * output byte-by-byte here. Else use wctomb().
*/ */
len = wcslen(start); len = wcslen(start);
maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); if (dlen) {
maxolen = *dlen;
if (maxolen == 0) {
errno = ENOSPC;
goto out;
}
} else {
if (len > (SIZE_MAX - 1)/MB_LEN_MAX) {
errno = ENOSPC;
goto out;
}
maxolen = len*MB_LEN_MAX + 1;
}
olen = 0; olen = 0;
bzero(&mbstate, sizeof(mbstate)); memset(&mbstate, 0, sizeof(mbstate));
for (dst = start; len > 0; len--) { for (dst = start; len > 0; len--) {
if (!cerr) { if (!cerr) {
/* /*
@ -614,6 +656,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
} }
/* Terminate the output string. */ /* Terminate the output string. */
assert(olen < maxolen);
*mbdst = '\0'; *mbdst = '\0';
if (flags & VIS_NOLOCALE) { if (flags & VIS_NOLOCALE) {

View File

@ -1,5 +1,4 @@
/* $NetBSD: vis.h,v 1.25 2017/04/23 01:57:36 christos Exp $ */ /* $NetBSD: vis.h,v 1.26 2022/05/20 21:31:24 andvar Exp $ */
/* $FreeBSD$ */
/*- /*-
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
@ -41,7 +40,7 @@
* to select alternate encoding format * to select alternate encoding format
*/ */
#define VIS_OCTAL 0x0001 /* use octal \ddd format */ #define VIS_OCTAL 0x0001 /* use octal \ddd format */
#define VIS_CSTYLE 0x0002 /* use \[nrft0..] where appropiate */ #define VIS_CSTYLE 0x0002 /* use \[nrft0..] where appropriate */
/* /*
* to alter set of characters encoded (default is to encode all * to alter set of characters encoded (default is to encode all