S390: Silence gcc 5.1 array-bounds warnings if build with -O3.
Stefan Liebler
stli@linux.vnet.ibm.com
Thu Jan 28 08:22:00 GMT 2016
Hi,
The gcc 5.1 reports some "array subscript is above array bounds"
warnings if compiled with -O3 on s390x. There are no warnings with -O2.
Older or newer GCCs do not report these warnings.
This patch silences these warnings with DIAG_* macros,
except the test-cases, where an assert is included.
Does anybody see these warnings on other architectures, too?
Is it okay to silence these warnings?
Here are the warnings with some comments:
gcc res_hconf.c -c -O3 ...
res_hconf.c: In function â_res_hconf_trim_domainsâ:
res_hconf.c:580:47: error: array subscript is above array bounds
[-Werror=array-bounds]
const char *trim = _res_hconf.trimdomain[i];
trimdomain is accessed in a loop in function _res_hconf_trim_domain(),
which is called in _res_hconf_trim_domains():
for (i = 0; i < _res_hconf.num_trimdomains; ++i)
{
const char *trim = _res_hconf.trimdomain[i];
...
and is declared in resolv/res_hconf.h:
#define TRIMDOMAINS_MAX 4
struct hconf
{
...
int num_trimdomains;
const char *trimdomain[TRIMDOMAINS_MAX];
...
};
extern struct hconf _res_hconf;
and defined in resolv/res_hconf.c:
struct hconf _res_hconf;
_res_hconf.num_trimdomains is only incremented in
static fucntion arg_trimdomain_list():
if (_res_hconf.num_trimdomains >= TRIMDOMAINS_MAX)
{
...
return 0;
}
_res_hconf.trimdomain[_res_hconf.num_trimdomains++] = __strndup (start,
len);
...
arg_trimdomain_list() is only called via do_init(), which is called via
__libc_once in _res_hconf_init().
As far as I saw, _res_hconf_trim_domains() is called after _res_hconf_init()
in inet/gethstbyad_r.c, which includes nss/getXXbyYY_r.c.
gcc gethnamaddr.c -c O3 ...
gethnamaddr.c: In function âaddrsortâ:
gethnamaddr.c:968:21: error: array subscript is above array bounds
[-Werror=array-bounds]
if (_res.sort_list[j].addr.s_addr ==
gethnamaddr.c:969:57: error: array subscript is above array bounds
[-Werror=array-bounds]
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
The same warning occurs in resolv/nss_dns/dns-host.c.
_res.sort_list is accessed in function addrsort() in gethnamaddr.c |
resolv/nss_dns/dns-host.c:
for (j = 0 ; (unsigned)j < _res.nsort; j++)
{
if (_res.sort_list[j].addr.s_addr ==
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
break;
...
It is declared in resolv/resolv.h:
# define MAXRESOLVSORT 10 /* number of net to sort on */
struct __res_state {
...
unsigned nsort:4; /* number of elements in sort_list[] */
...
struct {
struct in_addr addr;
u_int32_t mask;
} sort_list[MAXRESOLVSORT];
...
}
typedef struct __res_state *res_state;
and defined in resolv/res_libc.c:
struct __res_state _res __attribute__ ((nocommon));
__thread struct __res_state *__resp = &_res;
extern __thread struct __res_state *__libc_resp
__attribute__ ((alias ("__resp"))) attribute_hidden;
_res is a macro define:
include/resolv.h:21:# define _res (*__resp)
resolv/resolv.h:251:#define _res (*__res_state())
__res_state() returns __resp. See:
nptl/res.c:23:__res_state (void)
resolv/res-state.c:23:__res_state (void)
_res.nsort is only incremented in function __res_vinit() in
resolv/res_init.c:
__res_vinit(res_state statp, int preinit)
{
...
int nsort = 0;
...
while (nsort < MAXRESOLVSORT) {
...
nsort++;
...
}
...
statp->nsort = nsort;
addrsort() is called in resolv/gethnamaddr.c:
static struct hostent *getanswer () {
...
463: addrsort(h_addr_ptrs, haveanswer);
...
}
which is called in:
struct hostent *gethostbyname2 (const char *name, int af) {...
if (__res_maybe_init (&_res, 0) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
}
...
628: ret = getanswer(buf.buf, n, name, type);
...}
struct hostent * gethostbyaddr (const void *addr, socklen_t len, int af)
{...
if (__res_maybe_init (&_res, 0) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
...
727: hp = getanswer(buf.buf, n, qbuf, T_PTR);
...}
addrsort() is called in resolv/nss_dns/dns-host.c, too:
static enum nss_status getanswer_r () { ...
957:addrsort (host_data->h_addr_ptrs, haveanswer);
..}
which is called in:
enum nss_status _nss_dns_gethostbyname3_r () {...
if (__res_maybe_init (&_res, 0) == -1)
return NSS_STATUS_UNAVAIL;
...
245: status = getanswer_r (host_buffer.buf, n, name, type, result,
buffer, buflen,
errnop, h_errnop, map, ttlp, canonp);
...}
or in enum nss_status _nss_dns_gethostbyaddr2_r () {...
if (__res_maybe_init (&_res, 0) == -1)
return NSS_STATUS_UNAVAIL;
...
507: status = getanswer_r (host_buffer.buf, n, qbuf, T_PTR, result,
buffer, buflen,
...} errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
gcc programs/ld-ctype.c -c -O3
In file included from ../include/bits/string2.h:1:0,
from ../string/string.h:630,
from ../include/string.h:51,
from ../malloc/obstack.h:136,
from ../include/obstack.h:1,
from programs/ld-ctype.c:27:
programs/ld-ctype.c: In function âctype_readâ:
../string/bits/string2.h:807:7: error: array subscript is above array
bounds [-Werror=array-bounds]
: (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
^
programs/ld-ctype.c:2538:7: note: in expansion of macro âstrcmpâ
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
^
../string/bits/string2.h:807:7: error: array subscript is above array
bounds [-Werror=array-bounds]
: (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
^
programs/ld-ctype.c:2821:10: note: in expansion of macro âstrcmpâ
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
^
ctype->mapnames and ctype->classnames is accessed in function ctype_read():
void ctype_read(..) {...
struct locale_ctype_t *ctype;
...
ctype_startup (ldfile, result, charmap, copy_locale, ignore_content);
ctype = result->categories[LC_CTYPE].ctype;
...
ctype_class_new (.., ctype, ..);
...
ctype_map_new (.., ctype, ..);
...
for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
break;
...
for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
break;
...}
Both are declared in ld-ctype.c:
struct locale_ctype_t
{
#define MAX_NR_CHARCLASS (8 * sizeof (uint32_t))
size_t nr_charclass;
const char *classnames[MAX_NR_CHARCLASS];
#define MAX_NR_CHARMAP 16
const char *mapnames[MAX_NR_CHARMAP];
size_t map_collection_nr;
}
nr_charclass is only incremented in ctype_class_new(), which is called
in ctype_startup() or ctype_read():
static void ctype_class_new (struct linereader *lr, struct
locale_ctype_t *ctype,
const char *name) {...
if (ctype->nr_charclass == MAX_NR_CHARCLASS)
error ();
ctype->classnames[ctype->nr_charclass++] = name;
}
map_collection_nr is only incremented in ctype_map_new(), which is
called in ctype_startup() or ctype_read():
static void ctype_map_new (struct linereader *lr, struct locale_ctype_t
*ctype,
const char *name, const struct charmap_t *charmap) {...
if (ctype->map_collection_nr == MAX_NR_CHARMAP)
error ();
...
++ctype->map_collection_nr;
...}
gcc test-wmemcmp.c -c -O3 ...
In file included from ../string/test-memcmp.c:27:0,
from test-wmemcmp.c:2:
../string/test-memcmp.c: In function âcheck1â:
../string/test-string.h:135:19: warning: array subscript is above array
bounds [-Warray-bounds]
if (func_list[f].usable) \
^
../string/test-memcmp.c:446:7: note: in expansion of macro âFOR_EACH_IMPLâ
FOR_EACH_IMPL (impl, 0)
^
../string/test-string.h:137:22: warning: array subscript is above array
bounds [-Warray-bounds]
a->name = func_list[f].name; \
^
../string/test-memcmp.c:446:7: note: in expansion of macro âFOR_EACH_IMPLâ
FOR_EACH_IMPL (impl, 0)
^
../string/test-string.h:138:20: warning: array subscript is above array
bounds [-Warray-bounds]
a->fn = func_list[f].fn; \
^
../string/test-memcmp.c:446:7: note: in expansion of macro âFOR_EACH_IMPLâ
FOR_EACH_IMPL (impl, 0)
^
func_list is accessed in FOR_EACH_IMPL, which is defined in
string/test-string.h:
#ifdef TEST_NAME
/* Increase size of FUNC_LIST if assert is triggered at run-time. */
# define FUNC_LIST_MAX 32
static struct libc_ifunc_impl func_list[FUNC_LIST_MAX];
..
# define FOR_EACH_IMPL(impl, notall) \
..
for (f = 0; f < func_count; f++) \
{ \
if (func_list[f].usable) \
...
func_count is setup in test_init() via a call to __libc_ifunc_impl_list(),
which is platform-dependent.
Thus I added an assert to check func_count.
static void test_init (void)
{
#ifdef TEST_NAME
func_count = __libc_ifunc_impl_list (TEST_NAME, func_list,
(sizeof func_list
/ sizeof func_list[0]));
#endif
gcc bug-regex17.c -c -O3
bug-regex17.c: In function âdo_testâ:
bug-regex17.c:91:8: error: array subscript is above array bounds
[-Werror=array-bounds]
if (rm[n].rm_so != tests[i].rm[n].rm_so
^
bug-regex17.c:91:32: error: array subscript is above array bounds
[-Werror=array-bounds]
if (rm[n].rm_so != tests[i].rm[n].rm_so
^
bug-regex17.c:92:20: error: array subscript is above array bounds
[-Werror=array-bounds]
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
^
bug-regex17.c:92:44: error: array subscript is above array bounds
[-Werror=array-bounds]
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
^
The same applies to the bug-regex11|18|30.c files.
After a regexec () call, the test compares the results in rm
with the expected results in tests[i].rm:
for (n = 0; n < tests[i].nmatch; ++n)
{
if (rm[n].rm_so != tests[i].rm[n].rm_so
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
{
if (tests[i].rm[n].rm_so == -1 && tests[i].rm[n].rm_eo == -1)
break;
...
Both rm[] and tests[i].rm[] arrays have 5 elements.
The highest tests[i].nmatch is 5 in bug-regex11.c and < 5 in the other
tests.
I've added an assert to check the bounds.
ChangeLog:
* resolv/res_hconf.c: Include <libc-internal.h>.
(_res_hconf_trim_domain): Ignore array-bounds warning.
* resolv/gethnamaddr.c: Include <libc-internal.h>.
(addrsort): Ignore array-bounds warning.
* resolv/nss_dns/dns-host.c: Likewise.
* locale/programs/ld-ctype.c: Include <libc-internal.h>.
(ctype_read): Ignore array-bounds warning.
* string/test-string.h: Include <assert.h>.
Define FUNC_LIST_MAX.
(FOR_EACH_IMPL): Add assert before accessing func_list[f].
* posix/bug-regex11.c: Include <assert.h>.
Define RM_MAX.
(main): Add assert before accessing rm[n] and tests[i].rm[n].
* posix/bug-regex18.c: Likewise.
* posix/bug-regex17.c: Include <assert.h>.
Define RM_MAX.
(do_test): Add assert before accessing rm[n] and tests[i].rm[n].
* posix/bug-regex30.c: Likewise.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 20160128_gcc51_O3_build_warnings.patch
Type: text/x-patch
Size: 12846 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20160128/66f69ede/attachment.bin>
More information about the Libc-alpha
mailing list