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