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:
Родитель
66ac3fb878
Коммит
7b9ef2bb91
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче