libiberty: avoid reading past end of buffer in strndup/xstrndup (PR c/78498)

gcc/ChangeLog:
	PR c/78498
	* selftest.c (selftest::assert_strndup_eq): New function.
	(selftest::test_strndup): New function.
	(selftest::test_libiberty): New function.
	(selftest::selftest_c_tests): Call test_libiberty.

gcc/testsuite/ChangeLog:
	PR c/78498
	* gcc.dg/format/pr78494.c: New test case.

libiberty/ChangeLog:
	PR c/78498
	* strndup.c (strlen): Delete decl.
	(strnlen): Add decl.
	(strndup): Call strnlen rather than strlen.
	* xstrndup.c (xstrndup): Likewise.

From-SVN: r243030
This commit is contained in:
David Malcolm 2016-11-30 14:50:43 +00:00 committed by David Malcolm
parent e6383ae7a7
commit e613205cef
7 changed files with 84 additions and 9 deletions

View File

@ -1,3 +1,11 @@
2016-11-30 David Malcolm <dmalcolm@redhat.com>
PR c/78498
* selftest.c (selftest::assert_strndup_eq): New function.
(selftest::test_strndup): New function.
(selftest::test_libiberty): New function.
(selftest::selftest_c_tests): Call test_libiberty.
2016-11-30 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/78610

View File

@ -198,6 +198,53 @@ read_file (const location &loc, const char *path)
return result;
}
/* Selftests for libiberty. */
/* Verify that both strndup and xstrndup generate EXPECTED
when called on SRC and N. */
static void
assert_strndup_eq (const char *expected, const char *src, size_t n)
{
char *buf = strndup (src, n);
if (buf)
ASSERT_STREQ (expected, buf);
free (buf);
buf = xstrndup (src, n);
ASSERT_STREQ (expected, buf);
free (buf);
}
/* Verify that strndup and xstrndup work as expected. */
static void
test_strndup ()
{
assert_strndup_eq ("", "test", 0);
assert_strndup_eq ("t", "test", 1);
assert_strndup_eq ("te", "test", 2);
assert_strndup_eq ("tes", "test", 3);
assert_strndup_eq ("test", "test", 4);
assert_strndup_eq ("test", "test", 5);
/* Test on an string without zero termination. */
const char src[4] = {'t', 'e', 's', 't'};
assert_strndup_eq ("", src, 0);
assert_strndup_eq ("t", src, 1);
assert_strndup_eq ("te", src, 2);
assert_strndup_eq ("tes", src, 3);
assert_strndup_eq ("test", src, 4);
}
/* Run selftests for libiberty. */
static void
test_libiberty ()
{
test_strndup ();
}
/* Selftests for the selftest system itself. */
/* Sanity-check the ASSERT_ macros with various passing cases. */
@ -245,6 +292,7 @@ test_read_file ()
void
selftest_c_tests ()
{
test_libiberty ();
test_assertions ();
test_named_temp_file ();
test_read_file ();

View File

@ -1,3 +1,8 @@
2016-11-30 David Malcolm <dmalcolm@redhat.com>
PR c/78498
* gcc.dg/format/pr78494.c: New test case.
2016-11-30 David Edelsohn <dje.gcc@gmail.com>
* g++.dg/debug/dwarf2/ref-1.C: Don't XFAIL scan-assembler-not on AIX.

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O2 -Wall -Wextra -fdiagnostics-show-caret" } */
void f (void)
{
__builtin_printf ("%i", ""); /* { dg-warning "expects argument of type" } */
/* { dg-begin-multiline-output "" }
__builtin_printf ("%i", "");
~^ ~~
%s
{ dg-end-multiline-output "" } */
}

View File

@ -1,3 +1,11 @@
2016-11-30 David Malcolm <dmalcolm@redhat.com>
PR c/78498
* strndup.c (strlen): Delete decl.
(strnlen): Add decl.
(strndup): Call strnlen rather than strlen.
* xstrndup.c (xstrndup): Likewise.
2016-11-29 Nathan Sidwell <nathan@acm.org>
* cp-demangle.c (d_print_comp_inner): Fix parameter indentation.

View File

@ -33,7 +33,7 @@ memory was available. The result is always NUL terminated.
#include "ansidecl.h"
#include <stddef.h>
extern size_t strlen (const char*);
extern size_t strnlen (const char *s, size_t maxlen);
extern PTR malloc (size_t);
extern PTR memcpy (PTR, const PTR, size_t);
@ -41,10 +41,7 @@ char *
strndup (const char *s, size_t n)
{
char *result;
size_t len = strlen (s);
if (n < len)
len = n;
size_t len = strnlen (s, n);
result = (char *) malloc (len + 1);
if (!result)

View File

@ -48,10 +48,7 @@ char *
xstrndup (const char *s, size_t n)
{
char *result;
size_t len = strlen (s);
if (n < len)
len = n;
size_t len = strnlen (s, n);
result = XNEWVEC (char, len + 1);