S390: Silence gcc 5.1 array-bounds warnings if build with -O3.

Message ID n8cj2d$vl3$1@ger.gmane.org
State Rejected
Headers

Commit Message

Stefan Liebler Jan. 28, 2016, 8:21 a.m. UTC
  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.
  

Comments

Andreas Schwab Jan. 28, 2016, 9:19 a.m. UTC | #1
Stefan Liebler <stli@linux.vnet.ibm.com> writes:

> 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.

If they are bugs in just a single (obsolete) version of gcc then we
shouldn't clutter the source just for that version.  Those that are
affected can always use --disable-werror.

Andreas.
  
Florian Weimer Jan. 28, 2016, 9:27 a.m. UTC | #2
On 01/28/2016 09:21 AM, Stefan Liebler wrote:
> 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?

Do you know if these warnings are related to GCC optimization decisions,
or are just there to educate the programmer?

Florian
  
Stefan Liebler Jan. 29, 2016, 9:44 a.m. UTC | #3
On 01/28/2016 10:19 AM, Andreas Schwab wrote:
> If they are bugs in just a single (obsolete) version of gcc then we
> shouldn't clutter the source just for that version.  Those that are
> affected can always use --disable-werror.
>
> Andreas.
>
That sounds fair.
  
Stefan Liebler Jan. 29, 2016, 9:44 a.m. UTC | #4
On 01/28/2016 10:27 AM, Florian Weimer wrote:
> Do you know if these warnings are related to GCC optimization decisions,
> or are just there to educate the programmer?
No I don't. I've only recognized them while building with different 
versions in gcc 5 series.
  

Patch

diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index 0fd141c..b43a640 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -41,6 +41,7 @@ 
 #include "locfile.h"
 
 #include <assert.h>
+#include <libc-internal.h>
 
 
 /* The bit used for representing a special class.  */
@@ -2535,8 +2536,16 @@  with character code range values one must use the absolute ellipsis `...'"));
 	      size_t cnt;
 
 	      for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
-		if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
-		  break;
+		{
+		  /* GCC 5.1 emits a "array subscript is above array bounds"
+		     warning if compiled with -O3. It does not occur with -O2.
+		     Older or newer GCCs does not emit this warning.  */
+		  DIAG_PUSH_NEEDS_COMMENT;
+		  DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
+		  if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
+		    break;
+		  DIAG_POP_NEEDS_COMMENT;
+		}
 
 	      if (cnt < ctype->map_collection_nr)
 		free (now->val.str.startmb);
@@ -2808,8 +2817,16 @@  previous definition was here")));
 	  /* This could mean one of several things.  First test whether
 	     it's a character class name.  */
 	  for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
-	    if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
-	      break;
+	    {
+	      /* GCC 5.1 emits a "array subscript is above array bounds"
+		 warning if compiled with -O3. It does not occur with -O2.
+		 Older or newer GCCs does not emit this warning.  */
+	      DIAG_PUSH_NEEDS_COMMENT;
+	      DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
+	      if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
+		break;
+	      DIAG_POP_NEEDS_COMMENT;
+	    }
 	  if (cnt < ctype->nr_charclass)
 	    {
 	      class_bit = _ISwbit (cnt);
@@ -2818,8 +2835,16 @@  previous definition was here")));
 	      goto read_charclass;
 	    }
 	  for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
-	    if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
-	      break;
+	    {
+	      /* GCC 5.1 emits a "array subscript is above array bounds"
+		 warning if compiled with -O3. It does not occur with -O2.
+		 Older or newer GCCs does not emit this warning.  */
+	      DIAG_PUSH_NEEDS_COMMENT;
+	      DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
+	      if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
+		break;
+	      DIAG_POP_NEEDS_COMMENT;
+	    }
 	  if (cnt < ctype->map_collection_nr)
 	    {
 	      mapidx = cnt;
diff --git a/posix/bug-regex11.c b/posix/bug-regex11.c
index d3abe73..6497064 100644
--- a/posix/bug-regex11.c
+++ b/posix/bug-regex11.c
@@ -22,6 +22,9 @@ 
 #include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
+
+#define RM_MAX 5
 
 /* Tests supposed to match.  */
 struct
@@ -29,7 +32,7 @@  struct
   const char *pattern;
   const char *string;
   int flags, nmatch;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
 } tests[] = {
   /* Test for newline handling in regex.  */
   { "[^~]*~", "\nx~y", 0, 2, { { 0, 3 }, { -1, -1 } } },
@@ -93,7 +96,7 @@  int
 main (void)
 {
   regex_t re;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
   size_t i;
   int n, ret = 0;
 
@@ -120,16 +123,19 @@  main (void)
 	}
 
       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)
+	{
+	  assert (n < RM_MAX);
+	  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;
+	      printf ("%s: regexec %zd match failure rm[%d] %d..%d\n",
+		      tests[i].pattern, i, n, rm[n].rm_so, rm[n].rm_eo);
+	      ret = 1;
 	      break;
-	    printf ("%s: regexec %zd match failure rm[%d] %d..%d\n",
-		    tests[i].pattern, i, n, rm[n].rm_so, rm[n].rm_eo);
-	    ret = 1;
-	    break;
-	  }
+	    }
+	}
 
       regfree (&re);
     }
diff --git a/posix/bug-regex17.c b/posix/bug-regex17.c
index 8b9edfb..0168103 100644
--- a/posix/bug-regex17.c
+++ b/posix/bug-regex17.c
@@ -23,6 +23,9 @@ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <locale.h>
+#include <assert.h>
+
+#define RM_MAX 5
 
 /* Tests supposed to match.  */
 struct
@@ -30,7 +33,7 @@  struct
   const char *pattern;
   const char *string;
   int flags, nmatch;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
 } tests[] = {
   /* U+00C4	\xc3\x84	LATIN CAPITAL LETTER A WITH DIAERESIS
      U+00D6	\xc3\x96	LATIN CAPITAL LETTER O WITH DIAERESIS
@@ -62,7 +65,7 @@  static int
 do_test (void)
 {
   regex_t re;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
   size_t i;
   int n, ret = 0;
 
@@ -88,16 +91,19 @@  do_test (void)
 	}
 
       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)
+	{
+	  assert (n < RM_MAX);
+	  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;
+	      printf ("regexec match failure rm[%d] %d..%d\n",
+		      n, rm[n].rm_so, rm[n].rm_eo);
+	      ret = 1;
 	      break;
-	    printf ("regexec match failure rm[%d] %d..%d\n",
-		    n, rm[n].rm_so, rm[n].rm_eo);
-	    ret = 1;
-	    break;
-	  }
+	    }
+	}
 
       regfree (&re);
     }
diff --git a/posix/bug-regex18.c b/posix/bug-regex18.c
index 6902f52..1a9c91b 100644
--- a/posix/bug-regex18.c
+++ b/posix/bug-regex18.c
@@ -23,6 +23,9 @@ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <locale.h>
+#include <assert.h>
+
+#define RM_MAX 5
 
 /* Tests supposed to match.  */
 struct
@@ -30,7 +33,7 @@  struct
   const char *pattern;
   const char *string;
   int flags, nmatch;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
 } tests[] = {
   /* \xc4\xb0		LATIN CAPITAL LETTER I WITH DOT ABOVE
      \xc4\xb1		LATIN SMALL LETTER DOTLESS I
@@ -55,7 +58,7 @@  int
 main (void)
 {
   regex_t re;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
   size_t i;
   int n, ret = 0;
 
@@ -81,16 +84,19 @@  main (void)
 	}
 
       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)
+	{
+	  assert (n < RM_MAX);
+	  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;
+	      printf ("regexec match failure rm[%d] %d..%d\n",
+		      n, rm[n].rm_so, rm[n].rm_eo);
+	      ret = 1;
 	      break;
-	    printf ("regexec match failure rm[%d] %d..%d\n",
-		    n, rm[n].rm_so, rm[n].rm_eo);
-	    ret = 1;
-	    break;
-	  }
+	    }
+	}
 
       regfree (&re);
     }
diff --git a/posix/bug-regex30.c b/posix/bug-regex30.c
index e1ddf08..18362e0 100644
--- a/posix/bug-regex30.c
+++ b/posix/bug-regex30.c
@@ -23,6 +23,9 @@ 
 #include <stdio.h>
 #include <stdlib.h>
 #include <locale.h>
+#include <assert.h>
+
+#define RM_MAX 5
 
 /* Tests supposed to match.  */
 struct
@@ -30,7 +33,7 @@  struct
   const char *pattern;
   const char *string;
   int flags, nmatch;
-  regmatch_t rm[5];
+  regmatch_t rm[RM_MAX];
 } tests[] = {
   /* U+0413	\xd0\x93	CYRILLIC CAPITAL LETTER GHE
      U+0420	\xd0\xa0        CYRILLIC CAPITAL LETTER ER
@@ -61,7 +64,7 @@  do_test (void)
   for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
     {
       regex_t re;
-      regmatch_t rm[5];
+      regmatch_t rm[RM_MAX];
       int n = regcomp (&re, tests[i].pattern, tests[i].flags);
       if (n != 0)
 	{
@@ -81,16 +84,19 @@  do_test (void)
 	}
 
       for (n = 0; n < tests[i].nmatch; ++n)
-	if (rm[n].rm_so != tests[i].rm[n].rm_so
+	{
+	  assert (n < RM_MAX);
+	  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)
+	    {
+	      if (tests[i].rm[n].rm_so == -1 && tests[i].rm[n].rm_eo == -1)
+		break;
+	      printf ("regexec match failure rm[%d] %d..%d\n",
+		      n, rm[n].rm_so, rm[n].rm_eo);
+	      ret = 1;
 	      break;
-	    printf ("regexec match failure rm[%d] %d..%d\n",
-		    n, rm[n].rm_so, rm[n].rm_eo);
-	    ret = 1;
-	    break;
-	  }
+	    }
+	}
 
       regfree (&re);
     }
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 3a8e9b1..502c883 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -71,6 +71,7 @@  static char sccsid[] = "@(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93";
 #include <ctype.h>
 #include <errno.h>
 #include <syslog.h>
+#include <libc-internal.h>
 
 #define RESOLVSORT
 
@@ -965,9 +966,17 @@  addrsort (char **ap, int num)
 	p = ap;
 	for (i = 0; i < num; i++, p++) {
 	    for (j = 0 ; (unsigned)j < _res.nsort; j++)
+	      {
+		/* GCC 5.1 emits a "array subscript is above array bounds"
+		   warning if compiled with -O3. It does not occur with -O2.
+		   Older or newer GCCs does not emit this warning.  */
+		DIAG_PUSH_NEEDS_COMMENT;
+		DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
 		if (_res.sort_list[j].addr.s_addr ==
 		    (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
 			break;
+		DIAG_POP_NEEDS_COMMENT;
+	      }
 	    aval[i] = j;
 	    if (needsort == 0 && i > 0 && j < aval[i-1])
 		needsort = i;
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index a255d5e..a27e776 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -86,6 +86,8 @@ 
 #include <resolv/mapv4v6addr.h>
 #include <resolv/mapv4v6hostent.h>
 
+#include <libc-internal.h>
+
 #define RESOLVSORT
 
 #if PACKETSZ > 65536
@@ -562,9 +564,17 @@  addrsort (char **ap, int num)
   for (i = 0; i < num; i++, p++)
     {
       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;
+	{
+	  /* GCC 5.1 emits a "array subscript is above array bounds"
+	     warning if compiled with -O3. It does not occur with -O2.
+	     Older or newer GCCs does not emit this warning.  */
+	  DIAG_PUSH_NEEDS_COMMENT;
+	  DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
+	  if (_res.sort_list[j].addr.s_addr ==
+	      (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+	    break;
+	  DIAG_POP_NEEDS_COMMENT;
+	}
       aval[i] = j;
       if (needsort == 0 && i > 0 && j < aval[i-1])
 	needsort = i;
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
index 5cd1289..1d95dba 100644
--- a/resolv/res_hconf.c
+++ b/resolv/res_hconf.c
@@ -46,6 +46,7 @@ 
 #include "res_hconf.h"
 #include <wchar.h>
 #include <atomic.h>
+#include <libc-internal.h>
 
 #if IS_IN (libc)
 # define fgets_unlocked __fgets_unlocked
@@ -577,7 +578,13 @@  _res_hconf_trim_domain (char *hostname)
 
   for (i = 0; i < _res_hconf.num_trimdomains; ++i)
     {
+      /* GCC 5.1 emits a "array subscript is above array bounds" warning
+	 if compiled with -O3. It does not occur with -O2.
+	 Older or newer GCCs does not emit this warning.  */
+      DIAG_PUSH_NEEDS_COMMENT;
+      DIAG_IGNORE_NEEDS_COMMENT (5.1, "-Warray-bounds");
       const char *trim = _res_hconf.trimdomain[i];
+      DIAG_POP_NEEDS_COMMENT;
 
       trim_len = strlen (trim);
       if (hostname_len > trim_len
diff --git a/string/test-string.h b/string/test-string.h
index 728a7c2..9e35aaf 100644
--- a/string/test-string.h
+++ b/string/test-string.h
@@ -51,6 +51,7 @@  extern impl_t __start_impls[], __stop_impls[];
 #include <errno.h>
 #include <time.h>
 #include <ifunc-impl-list.h>
+#include <assert.h>
 #define GL(x) _##x
 #define GLRO(x) _##x
 
@@ -106,7 +107,8 @@  size_t iterations = 100000;
 
 #ifdef TEST_NAME
 /* Increase size of FUNC_LIST if assert is triggered at run-time.  */
-static struct libc_ifunc_impl func_list[32];
+# define FUNC_LIST_MAX 32
+static struct libc_ifunc_impl func_list[FUNC_LIST_MAX];
 static int func_count;
 static int impl_count = -1;
 static impl_t *impl_array;
@@ -132,13 +134,16 @@  static impl_t *impl_array;
 	    if (impl != skip)						\
 	      *a++ = *impl;						\
 	  for (f = 0; f < func_count; f++)				\
-	    if (func_list[f].usable)					\
-	      {								\
-		a->name = func_list[f].name;				\
-		a->fn = func_list[f].fn;				\
-		a->test = 1;						\
-		a++;							\
-	      }								\
+	    {								\
+	      assert (f < FUNC_LIST_MAX);				\
+	      if (func_list[f].usable)					\
+		{							\
+		  a->name = func_list[f].name;				\
+		  a->fn = func_list[f].fn;				\
+		  a->test = 1;						\
+		  a++;							\
+		}							\
+	    }								\
 	  impl_count = a - impl_array;					\
 	}								\
       else								\