Merge "Sync with upstream OpenBSD."

This commit is contained in:
Elliott Hughes 2020-07-31 23:47:05 +00:00 committed by Gerrit Code Review
commit 907e0aebd2
16 changed files with 503 additions and 381 deletions

View file

@ -525,6 +525,7 @@ cc_library_static {
"upstream-openbsd/lib/libc/stdlib/llabs.c",
"upstream-openbsd/lib/libc/stdlib/lldiv.c",
"upstream-openbsd/lib/libc/stdlib/lsearch.c",
"upstream-openbsd/lib/libc/stdlib/recallocarray.c",
"upstream-openbsd/lib/libc/stdlib/remque.c",
"upstream-openbsd/lib/libc/stdlib/setenv.c",
"upstream-openbsd/lib/libc/stdlib/tfind.c",

View file

@ -3004,7 +3004,7 @@ POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -4244,7 +4244,7 @@ SUCH DAMAGE.
-------------------------------------------------------------------
Copyright (c) 2005-2014 Rich Felker
Copyright (c) 2005-2018 Rich Felker
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -4602,7 +4602,23 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-------------------------------------------------------------------
Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -72,3 +72,7 @@ __LIBC_HIDDEN__ extern const char* __bionic_get_shell_path();
__LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
__LIBC_HIDDEN__ extern char* _mktemp(char*);
// Only OpenBSD has this at the moment, and we're more likely to just say
// "malloc is always calloc", so we don't expose this as libc API.
__LIBC_HIDDEN__ void* recallocarray(void*, size_t, size_t, size_t);

View file

@ -1,8 +1,8 @@
/* $OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $ */
/* $OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $ */
/* Copyright (c) 2011, VMware, Inc.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
@ -13,7 +13,7 @@
* * Neither the name of the VMware, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@ -27,7 +27,7 @@
*/
/*
* Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
* Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -51,9 +51,9 @@
* Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
* from chapter 2. "Shell Command Language"
* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
* where; 1. A bracket expression starting with an unquoted <circumflex> '^'
* character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
* in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
* where; 1. A bracket expression starting with an unquoted <circumflex> '^'
* character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
* in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
* <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
* a valid bracket expression is treated as an ordinary character; 4. a differing
* number of consecutive slashes within pattern and string will NOT match;
@ -62,10 +62,10 @@
* Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
* from chapter 9, "Regular Expressions"
* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
* with no support for collating symbols, equivalence class expressions or
* character class expressions. A partial range expression with a leading
* with no support for collating symbols, equivalence class expressions or
* character class expressions. A partial range expression with a leading
* hyphen following a valid range expression will match only the ordinary
* <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
* <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
* 'a' through 'm', a <hyphen> '-', or a 'z').
*
* Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
@ -98,22 +98,21 @@
static int
classmatch(const char *pattern, char test, int foldcase, const char **ep)
{
struct cclass *cc;
const char *colon;
size_t len;
int rval = RANGE_NOMATCH;
const char * const mismatch = pattern;
const char *colon;
struct cclass *cc;
int rval = RANGE_NOMATCH;
size_t len;
if (*pattern != '[' || pattern[1] != ':') {
if (pattern[0] != '[' || pattern[1] != ':') {
*ep = mismatch;
return(RANGE_ERROR);
return RANGE_ERROR;
}
pattern += 2;
if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
*ep = mismatch;
return(RANGE_ERROR);
return RANGE_ERROR;
}
*ep = colon + 2;
len = (size_t)(colon - pattern);
@ -132,11 +131,11 @@ classmatch(const char *pattern, char test, int foldcase, const char **ep)
*ep = mismatch;
rval = RANGE_ERROR;
}
return(rval);
return rval;
}
/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled.
* EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
* EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
* however the "\/" sequence is advanced to '/'.
*
* Both pattern and string are **char to support pointer increment of arbitrary
@ -144,341 +143,347 @@ classmatch(const char *pattern, char test, int foldcase, const char **ep)
*/
static int fnmatch_ch(const char **pattern, const char **string, int flags)
{
const char * const mismatch = *pattern;
const int nocase = !!(flags & FNM_CASEFOLD);
const int escape = !(flags & FNM_NOESCAPE);
const int slash = !!(flags & FNM_PATHNAME);
int result = FNM_NOMATCH;
const char *startch;
int negate;
const char * const mismatch = *pattern;
const int nocase = !!(flags & FNM_CASEFOLD);
const int escape = !(flags & FNM_NOESCAPE);
const int slash = !!(flags & FNM_PATHNAME);
int result = FNM_NOMATCH;
const char *startch;
int negate;
if (**pattern == '[')
{
++*pattern;
if (**pattern == '[') {
++*pattern;
/* Handle negation, either leading ! or ^ operators (never both) */
negate = ((**pattern == '!') || (**pattern == '^'));
if (negate)
++*pattern;
/* Handle negation, either leading ! or ^ operators */
negate = (**pattern == '!') || (**pattern == '^');
if (negate)
++*pattern;
/* ']' is an ordinary character at the start of the range pattern */
if (**pattern == ']')
goto leadingclosebrace;
/* ']' is an ordinary char at the start of the range pattern */
if (**pattern == ']')
goto leadingclosebrace;
while (**pattern)
{
if (**pattern == ']') {
++*pattern;
/* XXX: Fix for MBCS character width */
++*string;
return (result ^ negate);
}
while (**pattern) {
if (**pattern == ']') {
++*pattern;
/* XXX: Fix for MBCS character width */
++*string;
return (result ^ negate);
}
if (escape && (**pattern == '\\')) {
++*pattern;
if (escape && (**pattern == '\\')) {
++*pattern;
/* Patterns must be terminated with ']', not EOS */
if (!**pattern)
break;
}
/* Patterns must terminate with ']', not EOS */
if (!**pattern)
break;
}
/* Patterns must be terminated with ']' not '/' */
if (slash && (**pattern == '/'))
break;
/* Patterns must terminate with ']' not '/' */
if (slash && (**pattern == '/'))
break;
/* Match character classes. */
if (classmatch(*pattern, **string, nocase, pattern)
== RANGE_MATCH) {
result = 0;
continue;
}
if (!**pattern)
break;
/* Match character classes. */
switch (classmatch(*pattern, **string, nocase, pattern)) {
case RANGE_MATCH:
result = 0;
continue;
case RANGE_NOMATCH:
/* Valid character class but no match. */
continue;
default:
/* Not a valid character class. */
break;
}
if (!**pattern)
break;
leadingclosebrace:
/* Look at only well-formed range patterns;
* "x-]" is not allowed unless escaped ("x-\]")
* XXX: Fix for locale/MBCS character width
*/
if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
{
startch = *pattern;
*pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
/* Look at only well-formed range patterns;
* "x-]" is not allowed unless escaped ("x-\]")
* XXX: Fix for locale/MBCS character width
*/
if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) {
startch = *pattern;
*pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
/* NOT a properly balanced [expr] pattern, EOS terminated
* or ranges containing a slash in FNM_PATHNAME mode pattern
* fall out to to the rewind and test '[' literal code path
*/
if (!**pattern || (slash && (**pattern == '/')))
break;
/*
* NOT a properly balanced [expr] pattern, EOS
* terminated or ranges containing a slash in
* FNM_PATHNAME mode pattern fall out to to the
* rewind and test '[' literal code path.
*/
if (!**pattern || (slash && (**pattern == '/')))
break;
/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
if ((**string >= *startch) && (**string <= **pattern))
result = 0;
else if (nocase && (isupper((unsigned char)**string) ||
isupper((unsigned char)*startch) ||
isupper((unsigned char)**pattern))
&& (tolower((unsigned char)**string) >=
tolower((unsigned char)*startch))
&& (tolower((unsigned char)**string) <=
tolower((unsigned char)**pattern)))
result = 0;
/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
if ((**string >= *startch) && (**string <= **pattern))
result = 0;
else if (nocase &&
(isupper((unsigned char)**string) ||
isupper((unsigned char)*startch) ||
isupper((unsigned char)**pattern)) &&
(tolower((unsigned char)**string) >=
tolower((unsigned char)*startch)) &&
(tolower((unsigned char)**string) <=
tolower((unsigned char)**pattern)))
result = 0;
++*pattern;
continue;
}
++*pattern;
continue;
}
/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
if ((**string == **pattern))
result = 0;
else if (nocase && (isupper((unsigned char)**string) ||
isupper((unsigned char)**pattern))
&& (tolower((unsigned char)**string) ==
tolower((unsigned char)**pattern)))
result = 0;
/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
if ((**string == **pattern))
result = 0;
else if (nocase && (isupper((unsigned char)**string) ||
isupper((unsigned char)**pattern)) &&
(tolower((unsigned char)**string) ==
tolower((unsigned char)**pattern)))
result = 0;
++*pattern;
}
++*pattern;
}
/*
* NOT a properly balanced [expr] pattern;
* Rewind and reset result to test '[' literal
*/
*pattern = mismatch;
result = FNM_NOMATCH;
} else if (**pattern == '?') {
/* Optimize '?' match before unescaping **pattern */
if (!**string || (slash && (**string == '/')))
return FNM_NOMATCH;
result = 0;
goto fnmatch_ch_success;
} else if (escape && (**pattern == '\\') && (*pattern)[1]) {
++*pattern;
}
/* NOT a properly balanced [expr] pattern; Rewind
* and reset result to test '[' literal
*/
*pattern = mismatch;
result = FNM_NOMATCH;
}
else if (**pattern == '?') {
/* Optimize '?' match before unescaping **pattern */
if (!**string || (slash && (**string == '/')))
return FNM_NOMATCH;
result = 0;
goto fnmatch_ch_success;
}
else if (escape && (**pattern == '\\') && (*pattern)[1]) {
++*pattern;
}
/* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
if (**string == **pattern)
result = 0;
else if (nocase && (isupper((unsigned char)**string) ||
isupper((unsigned char)**pattern)) &&
(tolower((unsigned char)**string) ==
tolower((unsigned char)**pattern)))
result = 0;
/* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
if (**string == **pattern)
result = 0;
else if (nocase && (isupper((unsigned char)**string) ||
isupper((unsigned char)**pattern))
&& (tolower((unsigned char)**string) ==
tolower((unsigned char)**pattern)))
result = 0;
/* Refuse to advance over trailing slash or nulls
*/
if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
return result;
/* Refuse to advance over trailing slash or NULs */
if (**string == '\0' || **pattern == '\0' ||
(slash && ((**string == '/') || (**pattern == '/'))))
return result;
fnmatch_ch_success:
++*pattern;
++*string;
return result;
++*pattern;
++*string;
return result;
}
int fnmatch(const char *pattern, const char *string, int flags)
{
static const char dummystring[2] = {' ', 0};
const int escape = !(flags & FNM_NOESCAPE);
const int slash = !!(flags & FNM_PATHNAME);
const int leading_dir = !!(flags & FNM_LEADING_DIR);
const char *strendseg;
const char *dummyptr;
const char *matchptr;
int wild;
/* For '*' wild processing only; surpress 'used before initialization'
* warnings with dummy initialization values;
*/
const char *strstartseg = NULL;
const char *mismatch = NULL;
int matchlen = 0;
static const char dummystring[2] = {' ', 0};
const int escape = !(flags & FNM_NOESCAPE);
const int slash = !!(flags & FNM_PATHNAME);
const int leading_dir = !!(flags & FNM_LEADING_DIR);
const char *dummyptr, *matchptr, *strendseg;
int wild;
/* For '*' wild processing only; suppress 'used before initialization'
* warnings with dummy initialization values;
*/
const char *strstartseg = NULL;
const char *mismatch = NULL;
int matchlen = 0;
if (*pattern == '*')
goto firstsegment;
if (*pattern == '*')
goto firstsegment;
while (*pattern && *string)
{
/* Pre-decode "\/" which has no special significance, and
* match balanced slashes, starting a new segment pattern
*/
if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
++pattern;
if (slash && (*pattern == '/') && (*string == '/')) {
++pattern;
++string;
}
while (*pattern && *string) {
/*
* Pre-decode "\/" which has no special significance, and
* match balanced slashes, starting a new segment pattern.
*/
if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
++pattern;
if (slash && (*pattern == '/') && (*string == '/')) {
++pattern;
++string;
}
firstsegment:
/* At the beginning of each segment, validate leading period behavior.
*/
if ((flags & FNM_PERIOD) && (*string == '.'))
{
if (*pattern == '.')
++pattern;
else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
pattern += 2;
else
return FNM_NOMATCH;
++string;
}
/*
* At the beginning of each segment, validate leading period
* behavior.
*/
if ((flags & FNM_PERIOD) && (*string == '.')) {
if (*pattern == '.')
++pattern;
else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
pattern += 2;
else
return FNM_NOMATCH;
++string;
}
/* Determine the end of string segment
*
* Presumes '/' character is unique, not composite in any MBCS encoding
*/
if (slash) {
strendseg = strchr(string, '/');
if (!strendseg)
strendseg = strchr(string, '\0');
}
else {
strendseg = strchr(string, '\0');
}
/*
* Determine the end of string segment. Presumes '/'
* character is unique, not composite in any MBCS encoding
*/
if (slash) {
strendseg = strchr(string, '/');
if (!strendseg)
strendseg = strchr(string, '\0');
} else {
strendseg = strchr(string, '\0');
}
/* Allow pattern '*' to be consumed even with no remaining string to match
*/
while (*pattern)
{
if ((string > strendseg)
|| ((string == strendseg) && (*pattern != '*')))
break;
/*
* Allow pattern '*' to be consumed even with no remaining
* string to match.
*/
while (*pattern) {
if ((string > strendseg) ||
((string == strendseg) && (*pattern != '*')))
break;
if (slash && ((*pattern == '/')
|| (escape && (*pattern == '\\')
&& (pattern[1] == '/'))))
break;
if (slash && ((*pattern == '/') ||
(escape && (*pattern == '\\') && (pattern[1] == '/'))))
break;
/* Reduce groups of '*' and '?' to n '?' matches
* followed by one '*' test for simplicity
*/
for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
{
if (*pattern == '*') {
wild = 1;
}
else if (string < strendseg) { /* && (*pattern == '?') */
/* XXX: Advance 1 char for MBCS locale */
++string;
}
else { /* (string >= strendseg) && (*pattern == '?') */
return FNM_NOMATCH;
}
}
/*
* Reduce groups of '*' and '?' to n '?' matches
* followed by one '*' test for simplicity.
*/
for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) {
if (*pattern == '*') {
wild = 1;
} else if (string < strendseg) { /* && (*pattern == '?') */
/* XXX: Advance 1 char for MBCS locale */
++string;
}
else { /* (string >= strendseg) && (*pattern == '?') */
return FNM_NOMATCH;
}
}
if (wild)
{
strstartseg = string;
mismatch = pattern;
if (wild) {
strstartseg = string;
mismatch = pattern;
/* Count fixed (non '*') char matches remaining in pattern
* excluding '/' (or "\/") and '*'
*/
for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
{
if ((*matchptr == '\0')
|| (slash && ((*matchptr == '/')
|| (escape && (*matchptr == '\\')
&& (matchptr[1] == '/')))))
{
/* Compare precisely this many trailing string chars,
* the resulting match needs no wildcard loop
*/
/* XXX: Adjust for MBCS */
if (string + matchlen > strendseg)
return FNM_NOMATCH;
/*
* Count fixed (non '*') char matches remaining
* in pattern * excluding '/' (or "\/") and '*'.
*/
for (matchptr = pattern, matchlen = 0; 1; ++matchlen) {
if ((*matchptr == '\0') ||
(slash && ((*matchptr == '/') ||
(escape && (*matchptr == '\\') &&
(matchptr[1] == '/'))))) {
/* Compare precisely this many
* trailing string chars, the
* resulting match needs no
* wildcard loop.
*/
/* XXX: Adjust for MBCS */
if (string + matchlen > strendseg)
return FNM_NOMATCH;
string = strendseg - matchlen;
wild = 0;
break;
}
string = strendseg - matchlen;
wild = 0;
break;
}
if (*matchptr == '*')
{
/* Ensure at least this many trailing string chars remain
* for the first comparison
*/
/* XXX: Adjust for MBCS */
if (string + matchlen > strendseg)
return FNM_NOMATCH;
if (*matchptr == '*') {
/*
* Ensure at least this many
* trailing string chars remain
* for the first comparison.
*/
/* XXX: Adjust for MBCS */
if (string + matchlen > strendseg)
return FNM_NOMATCH;
/* Begin first wild comparison at the current position */
break;
}
/*
* Begin first wild comparison
* at the current position.
*/
break;
}
/* Skip forward in pattern by a single character match
* Use a dummy fnmatch_ch() test to count one "[range]" escape
*/
/* XXX: Adjust for MBCS */
if (escape && (*matchptr == '\\') && matchptr[1]) {
matchptr += 2;
}
else if (*matchptr == '[') {
dummyptr = dummystring;
fnmatch_ch(&matchptr, &dummyptr, flags);
}
else {
++matchptr;
}
}
}
/*
* Skip forward in pattern by a single
* character match Use a dummy
* fnmatch_ch() test to count one
* "[range]" escape.
*/
/* XXX: Adjust for MBCS */
if (escape && (*matchptr == '\\') &&
matchptr[1]) {
matchptr += 2;
} else if (*matchptr == '[') {
dummyptr = dummystring;
fnmatch_ch(&matchptr, &dummyptr,
flags);
} else {
++matchptr;
}
}
}
/* Incrementally match string against the pattern
*/
while (*pattern && (string < strendseg))
{
/* Success; begin a new wild pattern search
*/
if (*pattern == '*')
break;
/* Incrementally match string against the pattern. */
while (*pattern && (string < strendseg)) {
/* Success; begin a new wild pattern search. */
if (*pattern == '*')
break;
if (slash && ((*string == '/')
|| (*pattern == '/')
|| (escape && (*pattern == '\\')
&& (pattern[1] == '/'))))
break;
if (slash && ((*string == '/') ||
(*pattern == '/') || (escape &&
(*pattern == '\\') && (pattern[1] == '/'))))
break;
/* Compare ch's (the pattern is advanced over "\/" to the '/',
* but slashes will mismatch, and are not consumed)
*/
if (!fnmatch_ch(&pattern, &string, flags))
continue;
/*
* Compare ch's (the pattern is advanced over
* "\/" to the '/', but slashes will mismatch,
* and are not consumed).
*/
if (!fnmatch_ch(&pattern, &string, flags))
continue;
/* Failed to match, loop against next char offset of string segment
* until not enough string chars remain to match the fixed pattern
*/
if (wild) {
/* XXX: Advance 1 char for MBCS locale */
string = ++strstartseg;
if (string + matchlen > strendseg)
return FNM_NOMATCH;
/*
* Failed to match, loop against next char
* offset of string segment until not enough
* string chars remain to match the fixed
* pattern.
*/
if (wild) {
/* XXX: Advance 1 char for MBCS locale */
string = ++strstartseg;
if (string + matchlen > strendseg)
return FNM_NOMATCH;
pattern = mismatch;
continue;
}
else
return FNM_NOMATCH;
}
}
pattern = mismatch;
continue;
} else
return FNM_NOMATCH;
}
}
if (*string && !((slash || leading_dir) && (*string == '/')))
return FNM_NOMATCH;
if (*string && !((slash || leading_dir) && (*string == '/')))
return FNM_NOMATCH;
if (*pattern && !(slash && ((*pattern == '/')
|| (escape && (*pattern == '\\')
&& (pattern[1] == '/')))))
return FNM_NOMATCH;
if (*pattern && !(slash && ((*pattern == '/') ||
(escape && (*pattern == '\\') && (pattern[1] == '/')))))
return FNM_NOMATCH;
if (leading_dir && !*pattern && *string == '/')
return 0;
}
if (leading_dir && !*pattern && *string == '/')
return 0;
}
/* Where both pattern and string are at EOS, declare success
*/
if (!*string && !*pattern)
return 0;
/* Where both pattern and string are at EOS, declare success. */
if (!*string && !*pattern)
return 0;
/* pattern didn't match to the end of string */
return FNM_NOMATCH;
/* Pattern didn't match to the end of string. */
return FNM_NOMATCH;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: mbtowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
/* $OpenBSD: mbtowc.c,v 1.3 2016/02/27 14:02:13 schwarze Exp $ */
/*-
* Copyright (c) 2002-2004 Tim J. Robbins.
@ -44,7 +44,14 @@ mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n)
return (0);
}
rval = mbrtowc(pwc, s, n, &mbs);
if (rval == (size_t)-1 || rval == (size_t)-2)
return (-1);
return ((int)rval);
switch (rval) {
case (size_t)-2:
errno = EILSEQ;
/* FALLTHROUGH */
case (size_t)-1:
return -1;
default:
return (int)rval;
}
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fgetln.c,v 1.13 2015/01/05 21:58:52 millert Exp $ */
/* $OpenBSD: fgetln.c,v 1.17 2017/03/17 14:53:08 deraadt Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@ -46,7 +46,7 @@ __slbexpand(FILE *fp, size_t newsize)
if (fp->_lb._size >= newsize)
return (0);
if ((p = realloc(fp->_lb._base, newsize)) == NULL)
if ((p = recallocarray(fp->_lb._base, fp->_lb._size, newsize, 1)) == NULL)
return (-1);
fp->_lb._base = p;
fp->_lb._size = newsize;
@ -76,7 +76,7 @@ fgetln(FILE *fp, size_t *lenp)
goto error;
/* look for a newline in the input */
if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
if ((p = memchr(fp->_p, '\n', fp->_r)) != NULL) {
/*
* Found one. Flag buffer as modified to keep fseek from
* `optimising' a backward seek, in case the user stomps on
@ -112,12 +112,14 @@ fgetln(FILE *fp, size_t *lenp)
*/
if (__slbexpand(fp, len + OPTIMISTIC))
goto error;
(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
len - off);
(void)memcpy(fp->_lb._base + off, fp->_p, len - off);
off = len;
if (__srefill(fp))
break; /* EOF or error: return partial line */
if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
if (__srefill(fp)) {
if (fp->_flags & __SEOF)
break;
goto error;
}
if ((p = memchr(fp->_p, '\n', fp->_r)) == NULL)
continue;
/* got it: finish up the line (like code above) */
@ -126,8 +128,7 @@ fgetln(FILE *fp, size_t *lenp)
len += diff;
if (__slbexpand(fp, len))
goto error;
(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
diff);
(void)memcpy(fp->_lb._base + off, fp->_p, diff);
fp->_r -= diff;
fp->_p = p;
break;
@ -142,3 +143,4 @@ error:
*lenp = 0;
return (NULL);
}
DEF_WEAK(fgetln);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fputwc.c,v 1.6 2015/10/01 02:32:07 guenther Exp $ */
/* $OpenBSD: fputwc.c,v 1.7 2016/01/26 13:57:02 schwarze Exp $ */
/* $NetBSD: fputwc.c,v 1.3 2003/03/07 07:11:37 tshiozak Exp $ */
/*-
@ -62,7 +62,7 @@ __fputwc_unlock(wchar_t wc, FILE *fp)
size = wcrtomb(buf, wc, st);
if (size == (size_t)-1) {
errno = EILSEQ;
fp->_flags |= __SERR;
return WEOF;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
/* $OpenBSD: fvwrite.c,v 1.20 2017/03/17 16:06:33 millert Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@ -35,6 +35,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "local.h"
#include "fvwrite.h"
@ -63,7 +64,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
}
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
#define COPY(n) (void)memcpy(fp->_p, p, n)
iov = uio->uio_iov;
p = iov->iov_base;
@ -105,15 +106,14 @@ __sfvwrite(FILE *fp, struct __suio *uio)
if ((fp->_flags & (__SALC | __SSTR)) ==
(__SALC | __SSTR) && fp->_w < len) {
size_t blen = fp->_p - fp->_bf._base;
int pgmsk = getpagesize() - 1;
unsigned char *_base;
int _size;
/* Allocate space exponentially. */
_size = fp->_bf._size;
do {
_size = (_size << 1) + 1;
} while (_size < blen + len);
_base = realloc(fp->_bf._base, _size + 1);
/* Round up to nearest page. */
_size = ((blen + len + 1 + pgmsk) & ~pgmsk) - 1;
_base = recallocarray(fp->_bf._base,
fp->_bf._size + 1, _size + 1, 1);
if (_base == NULL)
goto err;
fp->_w += _size - fp->_bf._size;
@ -164,7 +164,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
do {
GETIOV(nlknown = 0);
if (!nlknown) {
nl = memchr((void *)p, '\n', len);
nl = memchr(p, '\n', len);
nldist = nl ? nl + 1 - p : len + 1;
nlknown = 1;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: fwide.c,v 1.5 2015/08/31 02:53:57 guenther Exp $ */
/* $OpenBSD: fwide.c,v 1.6 2019/12/03 05:03:37 asou Exp $ */
/* $NetBSD: fwide.c,v 1.2 2003/01/18 11:29:54 thorpej Exp $ */
/*-
@ -51,8 +51,10 @@ fwide(FILE *fp, int mode)
FLOCKFILE(fp);
wcio = WCIO_GET(fp);
if (!wcio)
if (!wcio) {
FUNLOCKFILE(fp);
return 0; /* XXX */
}
if (wcio->wcio_mode == 0 && mode != 0)
wcio->wcio_mode = mode;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: getdelim.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
/* $OpenBSD: getdelim.c,v 1.6 2017/04/13 18:36:51 brynet Exp $ */
/* $NetBSD: getdelim.c,v 1.13 2011/07/22 23:12:30 joerg Exp $ */
/*
@ -73,7 +73,7 @@ getdelim(char **__restrict buf, size_t *__restrict buflen,
}
/* Scan through looking for the separator */
p = memchr(fp->_p, sep, (size_t)fp->_r);
p = memchr(fp->_p, sep, fp->_r);
if (p == NULL)
len = fp->_r;
else
@ -103,7 +103,7 @@ getdelim(char **__restrict buf, size_t *__restrict buflen,
newlen++;
}
newb = realloc(*buf, newlen);
newb = recallocarray(*buf, *buflen, newlen, 1);
if (newb == NULL)
goto error;
*buf = newb;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: open_memstream.c,v 1.6 2015/08/31 02:53:57 guenther Exp $ */
/* $OpenBSD: open_memstream.c,v 1.8 2019/05/02 08:30:10 yasuoka Exp $ */
/*
* Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
@ -50,7 +50,7 @@ memstream_write(void *v, const char *b, int l)
if (sz < end + 1)
sz = end + 1;
p = realloc(st->string, sz);
p = recallocarray(st->string, st->size, sz, 1);
if (!p)
return (-1);
bzero(p + st->size, sz - st->size);
@ -76,7 +76,7 @@ static fpos_t
memstream_seek(void *v, fpos_t off, int whence)
{
struct state *st = v;
ssize_t base = 0;
size_t base = 0;
switch (whence) {
case SEEK_SET:
@ -89,7 +89,7 @@ memstream_seek(void *v, fpos_t off, int whence)
break;
}
if (off > SIZE_MAX - base || off < -base) {
if ((off > 0 && off > SIZE_MAX - base) || (off < 0 && base < -off)) {
errno = EOVERFLOW;
return (-1);
}

View file

@ -1,7 +1,7 @@
/* $OpenBSD: vasprintf.c,v 1.19 2015/12/28 22:08:18 mmcc Exp $ */
/* $OpenBSD: vasprintf.c,v 1.23 2019/01/25 00:19:25 millert Exp $ */
/*
* Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
* Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -20,31 +20,40 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "local.h"
#define INITIAL_SIZE 128
int
vasprintf(char **str, const char *fmt, __va_list ap)
{
int ret;
FILE f;
struct __sfileext fext;
unsigned char *_base;
const int pgsz = getpagesize();
_FILEEXT_SETUP(&f, &fext);
f._file = -1;
f._flags = __SWR | __SSTR | __SALC;
f._bf._base = f._p = malloc(128);
f._bf._base = f._p = malloc(INITIAL_SIZE);
if (f._bf._base == NULL)
goto err;
f._bf._size = f._w = 127; /* Leave room for the NUL */
f._bf._size = f._w = INITIAL_SIZE - 1; /* leave room for the NUL */
ret = __vfprintf(&f, fmt, ap);
if (ret == -1)
goto err;
*f._p = '\0';
_base = realloc(f._bf._base, ret + 1);
if (_base == NULL)
goto err;
*str = (char *)_base;
if (ret + 1 > INITIAL_SIZE && ret + 1 < pgsz / 2) {
/* midsize allocations can try to conserve memory */
unsigned char *_base = recallocarray(f._bf._base,
f._bf._size + 1, ret + 1, 1);
if (_base == NULL)
goto err;
*str = (char *)_base;
} else
*str = (char *)f._bf._base;
return (ret);
err:

View file

@ -1,4 +1,4 @@
/* $OpenBSD: vdprintf.c,v 1.2 2015/08/31 02:53:57 guenther Exp $ */
/* $OpenBSD: vdprintf.c,v 1.3 2019/03/03 16:41:41 semarie Exp $ */
/* $FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.4 2012/11/17 01:49:40 svnexp Exp $ */
/*-
@ -69,6 +69,6 @@ vdprintf(int fd, const char * __restrict fmt, va_list ap)
if ((ret = __vfprintf(&f, fmt, ap)) < 0)
return ret;
return fflush(&f) ? EOF : ret;
return __sflush(&f) ? EOF : ret;
}
DEF_WEAK(vdprintf);

View file

@ -0,0 +1,81 @@
/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
/*
* Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
{
size_t oldsize, newsize;
void *newptr;
if (ptr == NULL)
return calloc(newnmemb, size);
if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
newnmemb > 0 && SIZE_MAX / newnmemb < size) {
errno = ENOMEM;
return NULL;
}
newsize = newnmemb * size;
if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
errno = EINVAL;
return NULL;
}
oldsize = oldnmemb * size;
/*
* Don't bother too much if we're shrinking just a bit,
* we do not shrink for series of small steps, oh well.
*/
if (newsize <= oldsize) {
size_t d = oldsize - newsize;
if (d < oldsize / 2 && d < getpagesize()) {
memset((char *)ptr + newsize, 0, d);
return ptr;
}
}
newptr = malloc(newsize);
if (newptr == NULL)
return NULL;
if (newsize > oldsize) {
memcpy(newptr, ptr, oldsize);
memset((char *)newptr + oldsize, 0, newsize - oldsize);
} else
memcpy(newptr, ptr, newsize);
explicit_bzero(ptr, oldsize);
free(ptr);
return newptr;
}
DEF_WEAK(recallocarray);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: setenv.c,v 1.16 2015/09/13 08:31:47 guenther Exp $ */
/* $OpenBSD: setenv.c,v 1.19 2016/09/21 04:38:56 guenther Exp $ */
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
extern char **environ;
static char **lastenv; /* last value of environ */
/*
@ -44,7 +43,7 @@ int
putenv(char *str)
{
char **P, *cp;
size_t cnt;
size_t cnt = 0;
int offset = 0;
for (cp = str; *cp && *cp != '='; ++cp)
@ -66,13 +65,15 @@ putenv(char *str)
}
/* create new slot for string */
for (P = environ; *P != NULL; P++)
;
cnt = P - environ;
if (environ != NULL) {
for (P = environ; *P != NULL; P++)
;
cnt = P - environ;
}
P = reallocarray(lastenv, cnt + 2, sizeof(char *));
if (!P)
return (-1);
if (lastenv != environ)
if (lastenv != environ && environ != NULL)
memcpy(P, environ, cnt * sizeof(char *));
lastenv = environ = P;
environ[cnt] = str;
@ -123,22 +124,24 @@ setenv(const char *name, const char *value, int rewrite)
break;
}
} else { /* create new slot */
size_t cnt;
size_t cnt = 0;
for (P = environ; *P != NULL; P++)
;
cnt = P - environ;
if (environ != NULL) {
for (P = environ; *P != NULL; P++)
;
cnt = P - environ;
}
P = reallocarray(lastenv, cnt + 2, sizeof(char *));
if (!P)
return (-1);
if (lastenv != environ)
if (lastenv != environ && environ != NULL)
memcpy(P, environ, cnt * sizeof(char *));
lastenv = environ = P;
offset = cnt;
environ[cnt + 1] = NULL;
}
if (!(environ[offset] = /* name + `=' + value */
malloc((size_t)((int)(np - name) + l_value + 2))))
malloc((int)(np - name) + l_value + 2)))
return (-1);
for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
;

View file

@ -1,7 +1,7 @@
/* $OpenBSD: strstr.c,v 1.8 2018/04/30 07:44:56 denis Exp $ */
/* $OpenBSD: strstr.c,v 1.9 2020/04/16 12:37:52 claudio Exp $ */
/*
* Copyright (c) 2005-2014 Rich Felker
* Copyright (c) 2005-2018 Rich Felker
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -24,13 +24,8 @@
*/
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef DEBUG
#include <stdio.h>
#endif
static char *
twobyte_strstr(const unsigned char *h, const unsigned char *n)
{
@ -146,11 +141,8 @@ twoway_strstr(const unsigned char *h, const unsigned char *n)
/* Check last byte first; advance by shift on mismatch */
if (BITOP(byteset, h[l-1], &)) {
k = l-shift[h[l-1]];
#ifdef DEBUG
printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
#endif
if (k) {
if (mem0 && mem && k < p) k = l-p;
if (k < mem) k = mem;
h += k;
mem = 0;
continue;