Made corrections to remove compiler warnings for some conversions in … (#16)

* Made corrections to remove compiler warnings for some conversions in the network directory.

* Completed ns_parse.c plus some other fixes.

* Converted strlen so that we can remove the unchecked block around a call to strlen.

* Converted functions strcpy and stpcpy. Also removed unchecked blocks around calls to strcpy and strlen.

* Incorporated review comments.

* Incorporated review comments.

* Improved the performance of the newly implemented strnlen.
This commit is contained in:
Sulekha Kulkarni 2021-01-22 10:27:02 -08:00 коммит произвёл GitHub
Родитель 66ac3fb878
Коммит 7b9ef2bb91
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
26 изменённых файлов: 303 добавлений и 207 удалений

Просмотреть файл

@ -18,12 +18,11 @@ in_addr_t inet_network (const char *p : itype(_Nt_array_ptr<const char>));
char *inet_ntoa (struct in_addr in) : count(15) itype(_Nt_array_ptr<char>);
int inet_pton (int af,
const char *restrict s : itype(restrict _Nt_array_ptr<const char>),
void *restrict a0 : byte_count(af==AF_INET ? 4 : 8));
void *restrict a0 : byte_count(af==AF_INET ? 4 : 16));
const char *inet_ntop (int af,
const void *restrict a0 : byte_count(16),
char *restrict s : count(l),
const void *restrict a0 : byte_count(af==AF_INET ? 4 : 16),
char *restrict s : itype(restrict _Nt_array_ptr<char>) count(l),
socklen_t l) : itype(_Nt_array_ptr<const char>);
int inet_aton (const char *s0 : itype(_Nt_array_ptr<const char>),
struct in_addr *dest : itype(_Ptr<struct in_addr>));
struct in_addr inet_makeaddr(in_addr_t, in_addr_t);

Просмотреть файл

@ -37,7 +37,7 @@ typedef enum __ns_sect {
} ns_sect;
typedef struct __ns_msg {
const unsigned char *_msg : bounds(_msg, _eom), *_eom : itype(_Ptr<const unsigned char>);
const unsigned char *_msg : bounds(_msg, _eom), *_eom : itype(_Array_ptr<const unsigned char>);
uint16_t _id, _flags, _counts[ns_s_max] : itype(uint16_t _Nt_checked[ns_s_max]);
// _sections is a fixed-size array of _Array_ptr<const unsigned char>. The inner _Array_ptr has
// bounds(_msg_ptr, _eom). But we cannot specify bounds for an inner array in Checked C yet.
@ -45,7 +45,7 @@ typedef struct __ns_msg {
const unsigned char *_sections[ns_s_max] : itype(_Array_ptr<const unsigned char> _Checked[ns_s_max]);
ns_sect _sect;
int _rrnum;
const unsigned char *_msg_ptr : bounds(_msg_ptr, _eom) itype(_Array_ptr<const unsigned char>);
const unsigned char *_msg_ptr : bounds(_msg, _eom) itype(_Array_ptr<const unsigned char>);
} ns_msg;
struct _ns_flagdata { int mask, shift; };
@ -306,10 +306,10 @@ typedef enum __ns_cert_types {
#define NS_OPT_DNSSEC_OK 0x8000U
#define NS_OPT_NSID 3
#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2))
#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4))
#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2)
#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4)
#define NS_GET16(s, arg_cp, cp) (void)((s) = ns_get16(arg_cp)); (cp)+=2
#define NS_GET32(l, arg_cp, cp) (void)((l) = ns_get32(arg_cp)); (cp)+=4
#define NS_PUT16(s, arg_cp, cp) ns_put16((s), (arg_cp)); (cp)+=2
#define NS_PUT32(l, arg_cp, cp) ns_put32((l), (arg_cp)); (cp)+=4
// ns_get16 returns as an unsigned the concatenation of the 2 bytes pointed by cp in reversed order.
unsigned ns_get16(const unsigned char *cp : count(2));
@ -337,7 +337,7 @@ int ns_parserr(ns_msg *handle : itype(_Ptr<ns_msg>),
ns_rr *rr : itype(_Ptr<ns_rr>));
int ns_skiprr(const unsigned char *cp : bounds(cp, eom),
const unsigned char *eom : itype(_Ptr<const unsigned char>),
const unsigned char *eom : itype(_Array_ptr<const unsigned char>),
ns_sect section,
int count);
@ -345,8 +345,8 @@ int ns_skiprr(const unsigned char *cp : bounds(cp, eom),
// the result to dst which has size dst_size. eom is a pointer to the first byte after the message.
// It is used to make sure that ns_name_uncompress doesn't go past the end of the message.
int ns_name_uncompress(const unsigned char *msg : bounds(msg, eom),
const unsigned char *eom : itype(_Ptr<const unsigned char>),
const unsigned char *src : bounds(src, eom),
const unsigned char *eom : itype(_Array_ptr<const unsigned char>),
const unsigned char *src : bounds(msg, eom),
char *dst : count(dst_size) itype(_Array_ptr<char>),
size_t dst_size);

Просмотреть файл

@ -76,10 +76,10 @@ struct hostent {
#define h_addr h_addr_list[0]
struct servent {
char *s_name;
char **s_aliases;
char *s_name : itype(_Nt_array_ptr<char>);
char **s_aliases : itype(_Nt_array_ptr<_Nt_array_ptr<char>>);
int s_port;
char *s_proto;
char *s_proto : itype(_Nt_array_ptr<char>);
};
struct protoent {

Просмотреть файл

@ -162,11 +162,11 @@ int dn_comp(const char *src : itype(_Nt_array_ptr<const char>),
unsigned char **lastdnptr : count(0) itype(_Array_ptr<_Nt_array_ptr<unsigned char>>));
int dn_expand(const unsigned char *base : bounds(base, end),
const unsigned char *end : itype(_Array_ptr<const unsigned char>),
const unsigned char *src : bounds(src, end),
char *dest : count(space > 254 ? 254 : space),
const unsigned char *src : bounds(base, end),
char *dest : count(space),
int space);
int dn_skipname(const unsigned char *s : bounds(s, end),
const unsigned char *end : count(0));
const unsigned char *end : itype(_Array_ptr<const unsigned char>));
#ifdef __cplusplus
}

Просмотреть файл

@ -50,7 +50,7 @@ void *memchr (const void *src : itype(_Array_ptr<const void>) byte_count(n),
int c,
size_t n)
: itype(_Array_ptr<void>) byte_count(n);
char *strcpy (char *__restrict, const char *__restrict);
char *strcpy (char *__restrict dest, const char *__restrict src : itype(__restrict _Nt_array_ptr<const char>));
// Copies the first n characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
char *strncpy(char *__restrict d : itype(__restrict _Nt_array_ptr<char>) count(n),
const char *__restrict s,
@ -75,7 +75,7 @@ char *strpbrk (const char *, const char *);
char *strstr (const char *, const char *);
char *strtok (char *__restrict, const char *__restrict);
// Returns the length of string.
size_t strlen (const char * : itype(_Array_ptr<const char>));
size_t strlen (const char * : itype(_Nt_array_ptr<const char>));
char *strerror (int);
@ -88,7 +88,7 @@ char *strerror (int);
|| defined(_BSD_SOURCE)
char *strtok_r (char *__restrict, const char *__restrict, char **__restrict);
int strerror_r (int, char *, size_t);
char *stpcpy(char *__restrict, const char *__restrict);
char *stpcpy(char *__restrict, const char *__restrict : itype(__restrict _Nt_array_ptr<const char>));
// Copies at most n characters from the string pointed to by src, including the terminating null byte ('\0'),
// to the array pointed to by dest.
char *stpncpy(char *restrict d : itype(restrict _Array_ptr<char>) count(n),
@ -96,7 +96,8 @@ char *stpncpy(char *restrict d : itype(restrict _Array_ptr<char>) count(n),
size_t n)
:itype(_Array_ptr<char>) count(n);
// Returns the number of bytes in the string pointed to by s, excluding the terminating null byte ('\0').
size_t strnlen (const char * : itype(_Nt_array_ptr<const char>) count(n), size_t n);
size_t strnlen_array_ptr (const char * : itype(_Array_ptr<const char>) count(n), size_t n);
size_t strnlen (const char * : itype(_Nt_array_ptr<const char>), size_t n);
char *strdup (const char *);
char *strndup (const char *, size_t);
char *strsignal(int);

Просмотреть файл

@ -5,8 +5,8 @@
hidden int __dn_expand(const unsigned char *base : bounds(base, end),
const unsigned char *end : itype(_Array_ptr<const unsigned char>),
const unsigned char *src : bounds(src, end),
char *dest : count(space > 254 ? 254 : space),
const unsigned char *src : bounds(base, end),
char *dest : count(space),
int space);
hidden int __res_mkquery(int op,

Просмотреть файл

@ -4,7 +4,7 @@
#include "../../include/string.h"
hidden void *__memrchr(const void *, int, size_t);
hidden char *__stpcpy(char *, const char *);
hidden char *__stpcpy(char *restrict, const char *restrict : itype(restrict _Nt_array_ptr<const char>));
hidden char *__stpncpy(char *restrict d : itype(restrict _Array_ptr<char>) count(n),
const char *restrict s,
size_t n)

Просмотреть файл

@ -10,32 +10,30 @@
// getoffs labels start offsets of a compressed domain name s relative to base, which is
// the start of the domain name lists. The offsets are stored in the buffer offs with a
// max length of 128. Returns the size of offs actually used.
// Null-terminated strings base and s initially have unknown size, i.e., count(0).
static int getoffs(_Array_ptr<short> offs : count(128), // Fixed-size, allocated in match.
_Nt_array_ptr<const unsigned char> base,
_Nt_array_ptr<const unsigned char> s)
_Nt_array_ptr<const unsigned char> arg_base,
_Nt_array_ptr<const unsigned char> arg_s)
{
int i=0;
_Nt_array_ptr<const unsigned char> s_tmp : bounds(s, s + 0) = s;
_Nt_array_ptr<const unsigned char> s_widened : count(1) = 0;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
size_t len_s = strlen((_Nt_array_ptr<const char>)arg_s);
_Nt_array_ptr<const unsigned char> s : bounds(arg_s, arg_s + len_s) = 0;
_Nt_array_ptr<const unsigned char> base : bounds(arg_s, arg_s + len_s) = 0;
_Unchecked {
s = _Assume_bounds_cast<_Nt_array_ptr<const unsigned char>>(arg_s, bounds(arg_s, arg_s + len_s));
base = _Assume_bounds_cast<_Nt_array_ptr<const unsigned char>>
(arg_base, bounds(arg_s, arg_s + len_s));
}
for (;;) {
while (*s_tmp & 0xc0) {
if ((*s_tmp & 0xc0) != 0xc0) return 0;
// (*s & 0xc0) != 0 implies *s != 0. So we can widen the bounds of s.
// Manually widen the bounds for now. The compiler cannot figure it out yet.
_Unchecked {
s_widened = _Assume_bounds_cast<_Nt_array_ptr<const unsigned char>>(s_tmp, count(1));
}
// Decode offset and calculate the start position of the compressed domain name.
s_tmp = base + ((s_widened[0]&0x3f)<<8 | s_widened[1]);
while (*s & 0xc0) {
if ((*s & 0xc0) != 0xc0) return 0;
s = _Dynamic_bounds_cast<_Nt_array_ptr<const unsigned char>>
(base + ((s[0]&0x3f)<<8 | s[1]), bounds(arg_s, arg_s + len_s));
}
// s reaches the end of the domain name.
if (!*s_tmp) return i;
if (s_tmp-base >= 0x4000) return 0;
offs[i++] = s_tmp-base;
// Move to the next component.
s_tmp += *s_tmp + 1;
if (!*s) return i;
if (s-base >= 0x4000) return 0;
offs[i++] = s-base;
s += *s + 1;
}
}
@ -57,44 +55,50 @@ static int getlens(_Array_ptr<unsigned char> lens : count(127), // Fixed-size, a
// match matches the longest suffix of an ascii domain with a compressed domain name dn.
// Returns the length of the common suffix and store the offset.
// base and dn initially have count(0) prefixes. end points to the end of the unmatched
// part of the domain name src. The bounds of end are not passed as parameters but recovered
// indirectly from lens. Add parameter src to recover bounds information for end.
// arg_base and dn initially have count(0) prefixes.
// Add parameter arg_src to recover bounds information for arg_end.
// arg_end points to the end of the unmatched part of the domain name arg_src.
static int match(_Ptr<int> offset,
_Nt_array_ptr<const unsigned char> base,
_Nt_array_ptr<const unsigned char> arg_base,
_Nt_array_ptr<const unsigned char> dn,
_Array_ptr<const char> src : bounds(src, end),
_Array_ptr<const char> end : bounds(src, end),
_Array_ptr<const unsigned char> lens : count(nlen),
const int nlen)
_Array_ptr<const char> arg_src : bounds(arg_src, arg_end),
_Array_ptr<const char> arg_end : bounds(arg_src, arg_end),
_Array_ptr<const unsigned char> lens : count(arg_nlen),
const int arg_nlen)
{
int l, o, m=0;
short offs _Checked[128];
int noff = getoffs(offs, base, dn);
int noff = getoffs(offs, arg_base, dn);
if (!noff) return 0;
// Start from the end of the input domain name (src in dn_comp).
// Don't decrement nlen and access lens[nlen] at the same time because
// lens has count(nlen). Use a temporary ilen instead.
int ilen = nlen;
int nlen = arg_nlen;
_Array_ptr<const char> end : bounds(arg_src, arg_end) = arg_end;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
size_t len_base = strlen((_Nt_array_ptr<const char>)arg_base);
_Nt_array_ptr<const unsigned char> base : bounds(arg_base, arg_base + len_base) = 0;
_Unchecked { base = _Assume_bounds_cast<_Nt_array_ptr<const unsigned char>>
(arg_base, bounds(arg_base, arg_base + len_base)); }
for (;;) {
l = lens[--ilen];
l = lens[--nlen];
o = offs[--noff];
// Widen base using the offset o plus 1, since the first byte of base encodes the length.
_Nt_array_ptr<const unsigned char> base_widened : count(o + l + 1) = 0;
_Unchecked {
base_widened = _Assume_bounds_cast<_Nt_array_ptr<const unsigned char>>(base, count(o + l + 1));
}
end -= l;
size_t arg_l = l;
_Nt_array_ptr<const unsigned char> arg_base_1 : count(arg_l) =
_Dynamic_bounds_cast<_Nt_array_ptr<const unsigned char>>(base+o+1, count(arg_l));
_Array_ptr<const char> arg_end_1 : count(arg_l) =
_Dynamic_bounds_cast<_Array_ptr<const char>>(end, count(arg_l));
// Compare the suffixes. Return if not match.
if (l != base_widened[o] || memcmp(base_widened+o+1, end, l))
if (l != base[o] || memcmp(arg_base_1, arg_end_1, arg_l))
return m;
// We matched one component. Save offset and continue to the next.
*offset = o;
m += l;
if (ilen) m++;
if (!ilen || !noff) return m;
if (nlen) m++;
if (!nlen || !noff) return m;
end--;
}
}
@ -104,7 +108,7 @@ static int match(_Ptr<int> offset,
// message. The first pointer points to the beginning of the message and the list ends with NULL.
// The limit of the array is specified with lastdnptr. If dnptrs is NULL, domain names are not
// compressed. If lastdnptr is NULL, the list of labels is not updated.
int dn_comp(const char *src : itype(_Nt_array_ptr<const char>),
int dn_comp(const char *arg_src : itype(_Nt_array_ptr<const char>),
unsigned char *dst : count(space - 1) itype(_Nt_array_ptr<unsigned char>),
int space,
unsigned char **dnptrs : bounds(dnptrs, lastdnptr) itype(_Array_ptr<_Nt_array_ptr<unsigned char>>),
@ -113,29 +117,26 @@ int dn_comp(const char *src : itype(_Nt_array_ptr<const char>),
int i, j, n, m=0, offset, bestlen=0, bestoff;
unsigned char lens _Checked[127];
size_t l;
// TODO: bounds-safe interface for the 1st parameter of strnlen appears incorrect. It should
// accept an Nt_array_ptr with count(0).
_Unchecked {
l = strnlen((const char *)src, 255);
}
_Nt_array_ptr<const char> src_l : count(l) = 0;
_Unchecked {
src_l = _Assume_bounds_cast<_Nt_array_ptr<const char>>(src, count(l));
}
if (l && src_l[l-1] == '.') l--;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
l = strnlen(arg_src, 255);
_Nt_array_ptr<const char> src : count(l) = 0;
_Unchecked { src = _Assume_bounds_cast<_Nt_array_ptr<const char>>(arg_src, count(l)); }
if (l && src[l-1] == '.') l--;
if (l>253 || space<=0) return -1;
if (!l) {
*dst = 0;
return 1;
}
_Array_ptr<const char> end : bounds(src_l, end) = src_l + l;
n = getlens(lens, src_l, l);
_Array_ptr<const char> end : bounds(src, end) = src + l;
n = getlens(lens, src, l);
// Invariant: l = sum(lens) + n.
if (!n) return -1;
_Array_ptr<_Nt_array_ptr<unsigned char>> p : bounds(p, lastdnptr) = dnptrs;
_Array_ptr<unsigned char> arg_lens : count(n) =
_Dynamic_bounds_cast<_Array_ptr<unsigned char>>(lens, count(n));
_Array_ptr<_Nt_array_ptr<unsigned char>> p : bounds(dnptrs, lastdnptr) = dnptrs;
if (p && *p) for (p++; *p; p++) {
m = match(&offset, *dnptrs, *p, src_l, end, lens, n);
m = match(&offset, *dnptrs, *p, src, end, arg_lens, n);
if (m > bestlen) {
bestlen = m;
bestoff = offset;
@ -146,7 +147,11 @@ int dn_comp(const char *src : itype(_Nt_array_ptr<const char>),
/* encode unmatched part */
if (space < l-bestlen+2+(bestlen-1 < l-1)) return -1;
memcpy(dst+1, src_l, l-bestlen);
_Nt_array_ptr<unsigned char> arg_dst : count(l - bestlen) =
_Dynamic_bounds_cast<_Nt_array_ptr<unsigned char>>(dst + 1, count(l - bestlen));
_Nt_array_ptr<const char> arg_src_1 : count(l - bestlen) =
_Dynamic_bounds_cast<_Nt_array_ptr<const char>>(src, count(l - bestlen));
memcpy(arg_dst, arg_src_1, l-bestlen);
for (i=j=0; i<l-bestlen; i+=lens[j++]+1)
dst[i] = lens[j];
@ -161,7 +166,9 @@ int dn_comp(const char *src : itype(_Nt_array_ptr<const char>),
if (i>2 && lastdnptr && dnptrs && *dnptrs) {
while (*p) p++;
if (p+1 < lastdnptr) {
*p = dst;
_Nt_array_ptr<unsigned char> arg_dst_1 : count(0) =
_Dynamic_bounds_cast<_Nt_array_ptr<unsigned char>>(dst, count(0));
*p = arg_dst_1;
p++;
*p=0;
}

Просмотреть файл

@ -2,21 +2,19 @@
_Checked int __dn_expand(const unsigned char *base : bounds(base, end),
const unsigned char *end : itype(_Array_ptr<const unsigned char>),
const unsigned char *src : bounds(src, end),
char *dest : count(space > 254 ? 254 : space),
const unsigned char *src : bounds(base, end),
char *arg_dest : count(space),
int space)
{
const int space0 = space > 254 ? 254 : space;
_Array_ptr<const unsigned char> p : bounds(src, end) = src;
_Array_ptr<const unsigned char> p : bounds(base, end) = src;
int len = -1, i, j;
if (p==end || space <= 0) return -1;
const _Array_ptr<const char> dbegin : count(space0) = dest;
const _Array_ptr<const char> dend : count(0) = dest + space0;
// dst loops through bounds(dbegin, dend).
_Array_ptr<char> dst : bounds(dbegin, dend) = dest;
const _Ptr<const char> dbegin = _Dynamic_bounds_cast<_Ptr<const char>>(arg_dest);
const _Array_ptr<const char> dend : bounds(unknown) = arg_dest + (space > 254 ? 254 : space);
_Array_ptr<char> dest : bounds(arg_dest, arg_dest + space) = arg_dest;
/* detect reference loop using an iteration counter */
for (i=0; i < end-base; i+=2) {
/* loop invariants: p<end, dst<dend */
/* loop invariants: p<end, dest<=dend */
if (*p & 0xc0) {
if (p+1==end) return -1;
j = ((p[0] & 0x3f) << 8) | p[1];
@ -24,12 +22,12 @@ _Checked int __dn_expand(const unsigned char *base : bounds(base, end),
if (j >= end-base) return -1;
p = base+j;
} else if (*p) {
if (dst != dbegin) *dst++ = '.';
if (dest != dbegin) *dest++ = '.';
j = *p++;
if (j >= end-p || j >= dend-dst) return -1;
while (j--) *dst++ = *p++;
if (j >= end-p || j >= dend-dest) return -1;
while (j--) *dest++ = *p++;
} else {
*dst = 0;
*dest = 0;
if (len < 0) len = p+1-src;
return len;
}

Просмотреть файл

@ -1,9 +1,9 @@
#include <resolv.h>
_Checked int dn_skipname(const unsigned char *s : bounds(s, end),
const unsigned char *end : count(0))
const unsigned char *end : itype(_Array_ptr<const unsigned char>))
{
_Array_ptr<const unsigned char> p : bounds(p, end) = s;
_Array_ptr<const unsigned char> p : bounds(s, end) = s;
while (p < end)
if (!*p) return p-s+1;
else if (*p>=192)

Просмотреть файл

@ -11,11 +11,12 @@ int gethostbyaddr_r(const void *a : byte_count(l),
socklen_t l,
int af,
struct hostent *h : itype(_Ptr<struct hostent>),
char *buf_ori : count(buflen),
size_t buflen,
char *arg_buf : count(arg_buflen),
size_t arg_buflen,
struct hostent **res : itype(_Ptr<_Ptr<struct hostent>>),
int *err : itype(_Ptr<int>))
{
size_t buflen = arg_buflen;
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
@ -34,7 +35,7 @@ int gethostbyaddr_r(const void *a : byte_count(l),
}
/* Align buffer and check for space for pointers and ip address */
_Array_ptr<char> buf : bounds(buf_ori, buf_ori + buflen) = buf_ori;
_Array_ptr<char> buf : bounds(arg_buf, arg_buf + arg_buflen) = arg_buf;
i = (uintptr_t)buf & sizeof(char *)-1;
if (!i) i = sizeof(char *);
if (buflen <= 5*sizeof(char *)-i + l) return ERANGE;

Просмотреть файл

@ -11,7 +11,7 @@
int gethostbyname2_r(const char *name : itype(_Nt_array_ptr<const char>),
int af,
struct hostent *h : itype(_Ptr<struct hostent>),
char *buf_ori : count(buflen),
char *arg_buf : count(buflen),
size_t buflen,
struct hostent **res : itype(_Ptr<_Ptr<struct hostent>>),
int *err : itype(_Ptr<int>))
@ -43,15 +43,16 @@ int gethostbyname2_r(const char *name : itype(_Nt_array_ptr<const char>),
h->h_addrtype = af;
h->h_length = af==AF_INET6 ? 16 : 4;
_Array_ptr<char> buf : bounds(buf_ori, buf_ori + buflen) = buf_ori;
_Array_ptr<char> buf : bounds(arg_buf, arg_buf + buflen) = arg_buf;
/* Align buffer */
align = -(uintptr_t)buf & sizeof(char *)-1;
size_t name_len = strlen(name);
size_t canon_len = strlen(canon);
need = 4*sizeof(char *);
need += (cnt + 1) * (sizeof(char *) + h->h_length);
need += strlen(name)+1;
// TODO: strlen does not accept checked pointers yet.
need += strlen((const char *)canon)+1;
need += name_len+1;
need += canon_len+1;
need += align;
if (need > buflen) return ERANGE;
@ -70,13 +71,12 @@ int gethostbyname2_r(const char *name : itype(_Nt_array_ptr<const char>),
h->h_addr_list[i] = 0;
h->h_name = h->h_aliases[0] = buf;
// TODO: strlen does not accept checked pointers yet.
strcpy(h->h_name, (const char *)canon);
strncpy(h->h_name, (const char *)canon, canon_len+1);
buf += strlen(h->h_name)+1;
if (strcmp(h->h_name, name)) {
h->h_aliases[1] = buf;
strcpy(h->h_aliases[1], name);
strncpy(h->h_aliases[1], name, name_len+1);
buf += strlen(h->h_aliases[1])+1;
} else h->h_aliases[1] = 0;

Просмотреть файл

@ -13,7 +13,7 @@
int getservbyname_r(const char *name : itype(_Nt_array_ptr<const char>),
const char *prots : itype(_Nt_array_ptr<const char>),
struct servent *se : itype(_Ptr<struct servent>),
char *buf_ori : count(buflen),
char *arg_buf : count(buflen),
size_t buflen,
struct servent **res : itype(_Ptr<_Ptr<struct servent>>))
{
@ -27,7 +27,7 @@ int getservbyname_r(const char *name : itype(_Nt_array_ptr<const char>),
strtoul(name, &end, 10);
if (!*end) return ENOENT;
_Array_ptr<char> buf : bounds(buf_ori, buf_ori + buflen) = buf_ori;
_Array_ptr<char> buf : bounds(arg_buf, arg_buf + buflen) = arg_buf;
/* Align buffer */
align = -(uintptr_t)buf & ALIGN-1;
if (buflen < 2*sizeof(char *)+align)

Просмотреть файл

@ -10,17 +10,18 @@
int getservbyport_r(int port,
const char *prots : itype(_Nt_array_ptr<const char>),
struct servent *se : itype(_Ptr<struct servent>),
char *buf_ori : count(buflen),
size_t buflen,
char *arg_buf : count(arg_buflen),
size_t arg_buflen,
struct servent **res : itype(_Ptr<_Ptr<struct servent>>))
{
int i;
size_t buflen = arg_buflen;
struct sockaddr_in sin = {
.sin_family = AF_INET,
.sin_port = port,
};
_Array_ptr<char> buf : bounds(buf_ori, buf_ori + buflen) = buf_ori;
_Array_ptr<char> buf : bounds(arg_buf, arg_buf + arg_buflen) = arg_buf;
if (!prots) {
int r = getservbyport_r(port, "tcp", se, buf, buflen, res);
if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res);

Просмотреть файл

@ -3,32 +3,33 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#pragma CHECKED_SCOPE on
int __inet_aton(const char *s0 : itype(_Nt_array_ptr<const char>),
struct in_addr *dest : itype(_Ptr<struct in_addr>))
{
_Nt_array_ptr<const char> s = s0;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
unsigned int s_cnt = strlen(s0);
_Nt_array_ptr<const char> s : bounds(s0, s0 + s_cnt) = 0;
_Unchecked {s = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s0, count(s_cnt));}
// Struct in_addr has 32 bytes. Cast it to unsigned char pointer with count(4).
_Array_ptr<unsigned char> d : count(4) = (_Array_ptr<unsigned char>)dest;
unsigned long a _Checked[4] = { 0 };
_Array_ptr<char> z; // Bounds are not known until the call to strtoul.
_Nt_array_ptr<char> z : bounds(s0, s0 + s_cnt) = 0;
int i;
for (i=0; i<4; i++) {
// TODO: strtoul does not accept checked pointers yet.
// Since we cannot use address-of (&) operator on a checked pointer
// with bounds, we must widen the bounds of z using _Assume_bounds_cast
// after z is made point to the correct position in s through strtoul.
_Nt_array_ptr<char> zp = 0;
_Unchecked {
a[i] = strtoul((char *)s, (char **)&z, 0);
zp = _Assume_bounds_cast<_Nt_array_ptr<char>>(z, count(0));
char *zp;
a[i] = strtoul((const char *)s, &zp, 0);
z = _Assume_bounds_cast<_Nt_array_ptr<char>>(zp, bounds(s0, s0 + s_cnt));
}
if (z==s || (*zp && *zp != '.') || !isdigit(*s))
if (z==s || (*z && *z != '.') || !isdigit(*s))
return 0;
if (!*zp) break;
s=(_Nt_array_ptr<const char>)zp+1;
if (!*z) break;
s=z+1;
}
if (i==4) return 0;
switch (i) {

Просмотреть файл

@ -11,22 +11,26 @@
// pointer. The caller specifies the number of bytes available in this
// buffer in the argument l. a0 must have at least 16 bytes.
const char *inet_ntop(int af,
const void *restrict a0 : byte_count(16),
char *restrict s : count(l),
const void *restrict a0 : byte_count(af==AF_INET ? 4 : 16),
char *restrict s : itype(restrict _Nt_array_ptr<char>) count(l),
socklen_t l) : itype(_Nt_array_ptr<const char>)
{
_Array_ptr<const unsigned char> a : count(16) = a0;
int i, j, max, best;
char buf _Nt_checked[100];
switch (af) {
case AF_INET:
case AF_INET: {
_Array_ptr<const unsigned char> a : count(4) = 0;
a = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(a0, count(4));
_Unchecked {
if (snprintf(s, l, "%d.%d.%d.%d", a[0],a[1],a[2],a[3]) < l)
return s;
}
break;
case AF_INET6:
}
case AF_INET6: {
_Array_ptr<const unsigned char> a : count(16) = 0;
a = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(a0, count(16));
if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\377\377", 12)) _Unchecked {
snprintf((char *)buf, sizeof buf,
"%x:%x:%x:%x:%x:%x:%x:%x",
@ -53,15 +57,20 @@ const char *inet_ntop(int af,
}
if (max>3) {
buf[best] = buf[best+1] = ':';
memmove(buf+best+2, buf+best+max, i-best-max+1);
size_t arg_count = (size_t)(i-best-max+1);
_Array_ptr<char> buf_dest : count(arg_count) =
_Dynamic_bounds_cast<_Array_ptr<char>>(buf+best+2, count(arg_count));
_Array_ptr<char> buf_src : count(arg_count) =
_Dynamic_bounds_cast<_Array_ptr<char>>(buf+best+max, count(arg_count));
memmove(buf_dest, buf_src, arg_count);
}
_Unchecked {
if (strlen((char *)buf) < l) {
strcpy((char *)s, (char *)buf);
return s;
}
size_t buf_len = strlen(buf);
if (buf_len < l) {
_Unchecked {strncpy(s, (const char *)buf, buf_len+1);}
return s;
}
break;
}
default:
errno = EAFNOSUPPORT;
return 0;

Просмотреть файл

@ -19,22 +19,19 @@ static int hexval(unsigned c)
// AF_INET6. a0 is written in network byte order.
int inet_pton(int af,
const char *restrict s : itype(restrict _Nt_array_ptr<const char>),
void *restrict a0 : byte_count(af==AF_INET ? 4 : 8))
void *restrict a0 : byte_count(af==AF_INET ? 4 : 16))
{
uint16_t ip _Checked[8];
// Length of a that will be written.
const int count = af==AF_INET ? 4 : 16;
_Array_ptr<unsigned char> a : bounds(a0, (_Array_ptr<unsigned char>)a0 + count) = a0;
int i, j, v, d, brk=-1, need_v4=0;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
unsigned int s_cnt = strlen(s);
_Nt_array_ptr<const char> sw : bounds(s, s + s_cnt) = 0;
_Unchecked {sw = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s, count(s_cnt));}
// The length of s is unknown but it is 4 at max. Currently, the compiler
// cannot automatically widen its bounds in the for loop. So here we assume
// it has length 4 using _Assume_bounds_cast, which is the best we can do.
_Nt_array_ptr<const char> sw : count(4) = 0;
_Unchecked {
sw = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s, count(4));
}
if (af==AF_INET) {
_Array_ptr<unsigned char> a : bounds((_Array_ptr<unsigned char>)a0,
(_Array_ptr<unsigned char>)a0 + 4) = 0;
a = _Dynamic_bounds_cast<_Array_ptr<unsigned char>>(a0, count(4));
for (i=0; i<4; i++) {
for (v=j=0; j<3 && sw[j] && isdigit(sw[j]); j++)
v = 10*v + sw[j]-'0';
@ -50,6 +47,9 @@ int inet_pton(int af,
return -1;
}
_Array_ptr<unsigned char> a : bounds((_Array_ptr<unsigned char>)a0,
(_Array_ptr<unsigned char>)a0 + 16) = 0;
a = _Dynamic_bounds_cast<_Array_ptr<unsigned char>>(a0, count(16));
if (*sw==':' && *++sw!=':') return 0;
for (i=0; ; i++) {
@ -75,13 +75,20 @@ int inet_pton(int af,
sw += j+1;
}
if (brk>=0) {
memmove(ip+brk+7-i, ip+brk, 2*(i+1-brk));
size_t arg_count = (size_t)(2*(i+1-brk));
_Array_ptr<char> buf_dest : count(arg_count) =
_Dynamic_bounds_cast<_Array_ptr<char>>(ip+brk+7-i, count(arg_count));
_Array_ptr<char> buf_src : count(arg_count) =
_Dynamic_bounds_cast<_Array_ptr<char>>(ip+brk, count(arg_count));
memmove(buf_dest, buf_src, arg_count);
for (j=0; j<7-i; j++) ip[brk+j] = 0;
}
for (j=0; j<8; j++) {
*a++ = ip[j]>>8;
*a++ = ip[j];
}
if (need_v4 && inet_pton(AF_INET, sw, a-4) <= 0) return 0;
_Nt_array_ptr<char> arg_sw = _Dynamic_bounds_cast<_Nt_array_ptr<char>>(sw, count(0));
_Array_ptr<void> arg_a : byte_count(4) = _Dynamic_bounds_cast<_Array_ptr<void>>(a - 4, byte_count(4));
if (need_v4 && inet_pton(AF_INET, arg_sw, arg_a) <= 0) return 0;
return 1;
}

Просмотреть файл

@ -33,16 +33,18 @@ _Checked unsigned long ns_get32(const unsigned char *cp : count(4))
return (unsigned)cp[0]<<24 | cp[1]<<16 | cp[2]<<8 | cp[3];
}
_Checked void ns_put16(unsigned s, unsigned char *cp : count(2))
_Checked void ns_put16(unsigned s, unsigned char *arg_cp : count(2))
{
_Array_ptr<unsigned char> cp : bounds(arg_cp, arg_cp + 2) = arg_cp;
*cp = s>>8;
cp++;
*cp = s;
cp++;
}
_Checked void ns_put32(unsigned long l, unsigned char *cp : count(4))
_Checked void ns_put32(unsigned long l, unsigned char *arg_cp : count(4))
{
_Array_ptr<unsigned char> cp : bounds(arg_cp, arg_cp + 4) = arg_cp;
*cp = l>>24;
cp++;
*cp = l>>16;
@ -53,30 +55,32 @@ _Checked void ns_put32(unsigned long l, unsigned char *cp : count(4))
cp++;
}
_Checked int ns_initparse(const unsigned char *msg : count(msglen),
_Checked int ns_initparse(const unsigned char *arg_msg : count(msglen),
int msglen,
ns_msg *handle : itype(_Ptr<ns_msg>))
{
int i, r;
// Temporarily use an unchecked block to mask a compiler warning on inability to prove that the inferred
// bounds(msg, handle->_eom) implies bounds(msg, msg + msglen) on the assignment to handle->_msg.
// TODO(yahsun): the compiler should be able to prove the above bounds invariant when the two assignments
// are in a boundled block. So the warning(s) should disapear once boundled blocks are implemented.
_Unchecked {
handle->_msg = msg;
handle->_eom = msg + msglen;
}
_Array_ptr<const unsigned char> msg : bounds(arg_msg, arg_msg + msglen) = arg_msg;
handle->_eom = msg + msglen;
handle->_msg = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(msg, bounds(handle->_msg, handle->_eom));
if (msglen < (2 + ns_s_max) * NS_INT16SZ) goto bad;
// Invariant: msglen >= (2 + ns_s_max) * NS_INT16SZ.
NS_GET16(handle->_id, msg);
NS_GET16(handle->_flags, msg);
for (i = 0; i < ns_s_max; i++) NS_GET16(handle->_counts[i], msg);
_Array_ptr<const unsigned char> arg_msg_1 : count (2) = 0;
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(msg, count(2));
NS_GET16(handle->_id, arg_msg_1, msg);
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(msg, count(2));
NS_GET16(handle->_flags, arg_msg_1, msg);
for (i = 0; i < ns_s_max; i++) {
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(msg, count(2));
NS_GET16(handle->_counts[i], arg_msg_1, msg);
}
for (i = 0; i < ns_s_max; i++) {
if (handle->_counts[i]) {
handle->_sections[i] = msg;
r = ns_skiprr(msg, handle->_eom, i, handle->_counts[i]);
_Array_ptr<const unsigned char> arg_msg_2 : bounds(arg_msg_2, handle->_eom) =
_Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(msg, bounds(msg, handle->_eom));
r = ns_skiprr(arg_msg_2, handle->_eom, i, handle->_counts[i]);
if (r < 0) return -1;
msg += r;
} else {
@ -94,13 +98,14 @@ bad:
}
_Checked int ns_skiprr(const unsigned char *ptr: bounds(ptr, eom),
const unsigned char *eom : itype(_Ptr<const unsigned char>),
const unsigned char *eom : itype(_Array_ptr<const unsigned char>),
ns_sect section,
int count)
{
_Array_ptr<const unsigned char> p : bounds(ptr, eom) = ptr;
int r;
_Array_ptr<const unsigned char> arg_p : count (2) = 0;
while (count--) {
r = dn_skipname(p, eom);
if (r < 0) goto bad;
@ -109,7 +114,8 @@ _Checked int ns_skiprr(const unsigned char *ptr: bounds(ptr, eom),
if (section != ns_s_qd) {
if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad;
p += NS_INT32SZ;
NS_GET16(r, p);
arg_p = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(p, count(2));
NS_GET16(r, arg_p, p);
if (r > eom - p) goto bad;
p += r;
}
@ -148,7 +154,10 @@ _Checked int ns_parserr(ns_msg *handle : itype(_Ptr<ns_msg>),
}
}
if (rrnum > handle->_rrnum) {
r = ns_skiprr(handle->_msg_ptr, handle->_eom, section, rrnum - handle->_rrnum);
_Array_ptr<const unsigned char> arg_msg_ptr : bounds(arg_msg_ptr, handle->_eom) =
_Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(handle->_msg_ptr,
bounds(handle->_msg_ptr, handle->_eom));
r = ns_skiprr(arg_msg_ptr, handle->_eom, section, rrnum - handle->_rrnum);
if (r < 0) return -1;
handle->_msg_ptr += r;
handle->_rrnum = rrnum;
@ -157,12 +166,18 @@ _Checked int ns_parserr(ns_msg *handle : itype(_Ptr<ns_msg>),
if (r < 0) return -1;
handle->_msg_ptr += r;
if (2 * NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
NS_GET16(rr->type, handle->_msg_ptr);
NS_GET16(rr->rr_class, handle->_msg_ptr);
_Array_ptr<const unsigned char> arg_msg_1 : count (2) = 0;
_Array_ptr<const unsigned char> arg_msg_2 : count (4) = 0;
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(handle->_msg_ptr, count(2));
NS_GET16(rr->type, arg_msg_1, handle->_msg_ptr);
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(handle->_msg_ptr, count(2));
NS_GET16(rr->rr_class, arg_msg_1, handle->_msg_ptr);
if (section != ns_s_qd) {
if (NS_INT32SZ + NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
NS_GET32(rr->ttl, handle->_msg_ptr);
NS_GET16(rr->rdlength, handle->_msg_ptr);
arg_msg_2 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(handle->_msg_ptr, count(4));
NS_GET32(rr->ttl, arg_msg_2, handle->_msg_ptr);
arg_msg_1 = _Dynamic_bounds_cast<_Array_ptr<const unsigned char>>(handle->_msg_ptr, count(2));
NS_GET16(rr->rdlength, arg_msg_1, handle->_msg_ptr);
if (rr->rdlength > handle->_eom - handle->_msg_ptr) goto size;
rr->rdata = handle->_msg_ptr;
handle->_msg_ptr += rr->rdlength;
@ -191,13 +206,15 @@ size:
}
_Checked int ns_name_uncompress(const unsigned char *msg : bounds(msg, eom),
const unsigned char *eom : itype(_Ptr<const unsigned char>),
const unsigned char *src : bounds(src, eom),
const unsigned char *eom : itype(_Array_ptr<const unsigned char>),
const unsigned char *src : bounds(msg, eom),
char *dst : count(dstsiz) itype(_Array_ptr<char>),
size_t dstsiz)
{
int r;
r = dn_expand(msg, eom, src, dst, dstsiz);
_Array_ptr<char> arg_dst : bounds (arg_dst, arg_dst + (int)dstsiz) =
_Dynamic_bounds_cast<_Array_ptr<char>>(dst, bounds(dst, dst + (int)dstsiz));
r = dn_expand(msg, eom, src, arg_dst, dstsiz);
if (r < 0) errno = EMSGSIZE;
return r;
}

Просмотреть файл

@ -16,7 +16,7 @@ _Checked int recvmmsg(int fd,
struct timespec *timeout : itype(_Ptr<struct timespec>))
{
#if LONG_MAX > INT_MAX
_Array_ptr<struct mmsghdr> mh : count(vlen) = msgvec;
_Array_ptr<struct mmsghdr> mh : bounds(msgvec, msgvec + vlen) = msgvec;
unsigned int i;
for (i = vlen; i; i--, mh++)
mh->msg_hdr.__pad1 = mh->msg_hdr.__pad2 = 0;

Просмотреть файл

@ -3,7 +3,7 @@
#include <time.h>
_Checked int __res_mkquery(int op,
const char *dname : itype(_Nt_array_ptr<const char>),
const char *arg_dname : itype(_Nt_array_ptr<const char>),
int class,
int type,
const unsigned char *data : count(datalen),
@ -15,11 +15,12 @@ _Checked int __res_mkquery(int op,
int id, i, j;
unsigned char q _Checked[280];
struct timespec ts;
// TODO(yahsun): remove the unchecked scope once the str* functions are annotated with bounds-safe interfaces.
size_t l;
_Unchecked {
l = strnlen(dname, 255);
}
size_t l, bl;
// TODO: Cleanup the _Assume_bounds_cast once the strlen-based bounds widening is implemented.
bl = strnlen(arg_dname, 255);
_Nt_array_ptr<const char> dname : bounds(arg_dname, arg_dname + bl) = 0;
_Unchecked { dname = _Assume_bounds_cast<_Nt_array_ptr<const char>>(arg_dname, count(bl)); }
l = bl;
int n;
if (l && dname[l-1]=='.') l--;
@ -28,11 +29,16 @@ _Checked int __res_mkquery(int op,
return -1;
/* Construct query template - ID will be filled later */
memset(q, 0, n);
_Array_ptr<unsigned char> arg_q1 : count((size_t)n) =
_Dynamic_bounds_cast<_Array_ptr<unsigned char>>(q, count((size_t)n));
memset(arg_q1, 0, n);
q[2] = op*8 + 1;
q[3] = 32; /* AD */
q[5] = 1;
memcpy(q+13, dname, l);
_Array_ptr<unsigned char> arg_q2 : count(l) = _Dynamic_bounds_cast<_Array_ptr<unsigned char>>(q+13, count(l));
_Array_ptr<unsigned char> arg_dname1 : count(l) =
_Dynamic_bounds_cast<_Array_ptr<unsigned char>>(dname, count(l));
memcpy(arg_q2, arg_dname1, l);
for (i=13; q[i]; i=j+1) {
for (j=i; q[j] && q[j] != '.'; j++);
if (j-i-1u > 62u) return -1;
@ -49,7 +55,9 @@ _Checked int __res_mkquery(int op,
id = ts.tv_nsec + ts.tv_nsec/65536UL & 0xffff;
q[0] = id/256;
q[1] = id;
memcpy(buf, q, n);
_Array_ptr<unsigned char> arg_buf : count((size_t)n) =
_Dynamic_bounds_cast<_Array_ptr<unsigned char>>(buf, count((size_t)n));
memcpy(arg_buf, arg_q1, n);
return n;
}

Просмотреть файл

@ -10,7 +10,9 @@ _Checked int res_query(const char *name : itype(_Nt_array_ptr<const char>),
unsigned char q _Checked[280];
int ql = __res_mkquery(0, name, class, type, 0, 0, 0, q, sizeof q);
if (ql < 0) return ql;
return __res_send(q, ql, dest, len);
_Array_ptr<unsigned char> arg_q : count(ql) =
_Dynamic_bounds_cast<_Array_ptr<unsigned char>>(q, count(ql));
return __res_send(arg_q, ql, dest, len);
}
weak_alias(res_query, res_search);

Просмотреть файл

@ -1,23 +1,28 @@
#include <resolv.h>
#include <string.h>
_Checked int res_querydomain(const char *name : itype(_Nt_array_ptr<const char>),
const char *domain : itype(_Nt_array_ptr<const char>),
_Checked int res_querydomain(const char *arg_name : itype(_Nt_array_ptr<const char>),
const char *arg_domain : itype(_Nt_array_ptr<const char>),
int class,
int type,
unsigned char *dest : count(len),
int len)
{
char tmp _Nt_checked[255];
// TODO(yahsun): remove the unchecked scope once the str* functions are annotated with bounds-safe interfaces.
size_t nl, dl;
_Unchecked {
nl = strnlen(name, 255);
dl = strnlen(domain, 255);
nl = strnlen(arg_name, 255);
dl = strnlen(arg_domain, 255);
}
_Nt_array_ptr<const char> name : bounds(arg_name, arg_name + nl) = 0;
_Unchecked { name = _Assume_bounds_cast<_Nt_array_ptr<const char>>(arg_name, count(nl)); }
_Nt_array_ptr<const char> domain : bounds(arg_domain, arg_domain + dl) = 0;
_Unchecked { domain = _Assume_bounds_cast<_Nt_array_ptr<const char>>(arg_domain, count(dl)); }
if (nl+dl+1 > 254) return -1;
memcpy(tmp, name, nl);
_Nt_array_ptr<char> arg_tmp1 : count(nl) = _Dynamic_bounds_cast<_Nt_array_ptr<char>>(tmp, count(nl));
memcpy(arg_tmp1, name, nl);
tmp[nl] = '.';
memcpy(tmp+nl+1, domain, dl+1);
_Nt_array_ptr<char> arg_tmp2 : count(dl+1) = _Dynamic_bounds_cast<_Nt_array_ptr<char>>(tmp+nl+1, count(dl+1));
memcpy(arg_tmp2, domain, dl+1);
return res_query(tmp, class, type, dest, len);
}

Просмотреть файл

@ -7,21 +7,27 @@
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
char *__stpcpy(char *restrict d, const char *restrict s)
char *__stpcpy(char *restrict d, const char *restrict arg_s : itype(restrict _Nt_array_ptr<const char>))
{
_Nt_array_ptr<const char> s1 : bounds(arg_s, s1) = arg_s;
#ifdef __GNUC__
typedef size_t __attribute__((__may_alias__)) word;
word *wd;
const word *ws;
if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) {
if ((uintptr_t)s1 % ALIGN == (uintptr_t)d % ALIGN) {
const char *s = (const char *)s1;
for (; (uintptr_t)s % ALIGN; s++, d++)
if (!(*d=*s)) return d;
wd=(void *)d; ws=(const void *)s;
for (; !HASZERO(*ws); *wd++ = *ws++);
d=(void *)wd; s=(const void *)ws;
s1 = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s, bounds(arg_s, s));
}
#endif
for (; (*d=*s); s++, d++);
// TODO: The casting to const char * of s1 below is necessary until the issue with the
// widening of bounds of s1 (#938) is fixed in the compiler, in order to avoid test failures.
for (; (*d=*(const char *)s1); s1++, d++);
return d;
}

Просмотреть файл

@ -1,6 +1,6 @@
#include <string.h>
char *strcpy(char *restrict dest, const char *restrict src)
char *strcpy(char *restrict dest, const char *restrict src : itype(restrict _Nt_array_ptr<const char>))
{
__stpcpy(dest, src);
return dest;

Просмотреть файл

@ -7,16 +7,21 @@
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
size_t strlen(const char *s)
{
const char *a = s;
size_t strlen(const char *arg_s : itype(_Nt_array_ptr<const char>))
_Checked{
_Nt_array_ptr<const char> s1 : bounds(arg_s, s1) = arg_s;
#ifdef __GNUC__
_Unchecked {
const char *s = (const char *)s1;
typedef size_t __attribute__((__may_alias__)) word;
const word *w;
for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a;
for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-arg_s;
for (w = (const void *)s; !HASZERO(*w); w++);
s = (const void *)w;
s1 = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s, bounds(arg_s, s));
}
#endif
for (; *s; s++);
return s-a;
for (; *s1; s1++);
return s1-arg_s;
}

Просмотреть файл

@ -1,7 +1,36 @@
#include <string.h>
#include <stdint.h>
#include <limits.h>
size_t strnlen(const char *s : itype(_Nt_array_ptr<const char>) count(n), size_t n)
#define SS (sizeof(size_t))
#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
size_t strnlen_array_ptr(const char *s : itype(_Array_ptr<const char>) count(n), size_t n)
_Checked{
_Array_ptr<const char> p : count(n) = memchr(s, 0, n);
return p ? p-s : n;
}
size_t strnlen(const char *arg_s : itype(_Nt_array_ptr<const char>), size_t arg_n)
_Checked{
size_t n = arg_n;
_Nt_array_ptr<const char> s1 : bounds(arg_s, s1) = arg_s;
#ifdef __GNUC__
_Unchecked {
const char *s = (const char *)s1;
typedef size_t __attribute__((__may_alias__)) word;
const word *w;
for (; n && (uintptr_t)s & ALIGN; s++, n--) if (!*s) return s-arg_s;
for (w = (const void *)s; n >=SS && !HASZERO(*w); w++, n-=SS);
s = (const void *)w;
s1 = _Assume_bounds_cast<_Nt_array_ptr<const char>>(s, bounds(arg_s, s));
}
#endif
for (; n && *s1; s1++, n--);
return n ? s1-arg_s : arg_n;
}