* libio/bits/stdio2.h (__fread_chk, __fread_unlocked_chk): New

prototypes.
	(__fread_alias, __fread_unlocked_alias): New aliases.
	(fread): New extern inline.
	(fread_unlocked): Likewise.  Undef macro before definition of
	the inline function.
	* debug/Makefile (routines): Add fread_chk and fread_u_chk.
	(CFLAGS-fread_chk.c, CFLAGS-fread_u_chk.c): Add.
	* debug/Versions (libc): Export __fread_chk@@GLIBC_2.7
	and __fread_unlocked_chk@@GLIBC_2.7.
	* debug/fread_chk.c: New file.
	* debug/fread_u_chk.c: New file.
	* debug/tst-chk1.c (do_test): Add fread and fread_unlocked tests.
This commit is contained in:
Ulrich Drepper 2007-08-28 20:33:49 +00:00
parent cba5c7c073
commit 3586b2b60b
6 changed files with 213 additions and 2 deletions

View file

@ -1,3 +1,19 @@
2007-08-28 Jakub Jelinek <jakub@redhat.com>
* libio/bits/stdio2.h (__fread_chk, __fread_unlocked_chk): New
prototypes.
(__fread_alias, __fread_unlocked_alias): New aliases.
(fread): New extern inline.
(fread_unlocked): Likewise. Undef macro before definition of
the inline function.
* debug/Makefile (routines): Add fread_chk and fread_u_chk.
(CFLAGS-fread_chk.c, CFLAGS-fread_u_chk.c): Add.
* debug/Versions (libc): Export __fread_chk@@GLIBC_2.7
and __fread_unlocked_chk@@GLIBC_2.7.
* debug/fread_chk.c: New file.
* debug/fread_u_chk.c: New file.
* debug/tst-chk1.c (do_test): Add fread and fread_unlocked tests.
2007-08-27 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/syscalls.list

View file

@ -32,7 +32,7 @@ routines = backtrace backtracesyms backtracesymsfd noophooks \
gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \
read_chk pread_chk pread64_chk recv_chk recvfrom_chk \
readlink_chk readlinkat_chk getwd_chk getcwd_chk \
realpath_chk ptsname_r_chk \
realpath_chk ptsname_r_chk fread_chk fread_u_chk \
wctomb_chk wcscpy_chk wmemcpy_chk wmemmove_chk wmempcpy_chk \
wcpcpy_chk wcsncpy_chk wcscat_chk wcsncat_chk wmemset_chk \
wcpncpy_chk \
@ -58,6 +58,8 @@ CFLAGS-vfprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-gets_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-fgets_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-fgets_u_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-fread_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-fread_u_chk.c = -D_IO_MTSAFE_IO $(exceptions)
CFLAGS-swprintf_chk.c = -D_IO_MTSAFE_IO
CFLAGS-vswprintf_chk.c = -D_IO_MTSAFE_IO
CFLAGS-wprintf_chk.c = -D_IO_MTSAFE_IO $(exceptions)

View file

@ -39,4 +39,7 @@ libc {
GLIBC_2.5 {
__readlinkat_chk;
}
GLIBC_2.7 {
__fread_chk; __fread_unlocked_chk;
}
}

54
debug/fread_u_chk.c Normal file
View file

@ -0,0 +1,54 @@
/* Copyright (C) 1993, 1995, 1997, 1998, 1999, 2002, 2003, 2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
As a special exception, if you link the code in this file with
files compiled with a GNU compiler to produce an executable,
that does not cause the resulting executable to be covered by
the GNU Lesser General Public License. This exception does not
however invalidate any other reasons why the executable file
might be covered by the GNU Lesser General Public License.
This exception applies to code released by its copyright holders
in files containing the exception. */
#include "libioP.h"
#include <stdio.h>
size_t
__fread_unlocked_chk (void *__restrict ptr, size_t ptrlen,
size_t size, size_t n, FILE *__restrict stream)
{
size_t bytes_requested = size * n;
if (__builtin_expect ((n | size)
>= (((size_t) 1) << (8 * sizeof (size_t) / 2)), 0))
{
if (size != 0 && bytes_requested / size != n)
__chk_fail ();
}
if (__builtin_expect (bytes_requested > ptrlen, 0))
__chk_fail ();
CHECK_FILE (stream, 0);
if (bytes_requested == 0)
return 0;
size_t bytes_read
= INTUSE(_IO_sgetn) (stream, (char *) ptr, bytes_requested);
return bytes_requested == bytes_read ? n : bytes_read / size;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
/* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
@ -746,6 +746,75 @@ do_test (void)
CHK_FAIL_END
#endif
rewind (stdin);
if (fread (buf, 1, sizeof (buf), stdin) != sizeof (buf)
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread (buf, sizeof (buf), 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread (buf, sizeof (buf), l0 + 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fread (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fread (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
FAIL ();
CHK_FAIL_END
#endif
rewind (stdin);
if (fread_unlocked (buf, 1, sizeof (buf), stdin) != sizeof (buf)
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread_unlocked (buf, sizeof (buf), 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread_unlocked (buf, 1, 4, stdin) != 4
|| memcmp (buf, "abcdFGHI\na", 10))
FAIL ();
if (fread_unlocked (buf, 4, 1, stdin) != 1
|| memcmp (buf, "efghFGHI\na", 10))
FAIL ();
rewind (stdin);
if (fread_unlocked (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf)
|| memcmp (buf, "abcdefgh\nA", 10))
FAIL ();
if (fread_unlocked (buf, sizeof (buf), l0 + 1, stdin) != 1
|| memcmp (buf, "BCDEFGHI\na", 10))
FAIL ();
#if __USE_FORTIFY_LEVEL >= 1
CHK_FAIL_START
if (fread_unlocked (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1)
FAIL ();
CHK_FAIL_END
CHK_FAIL_START
if (fread_unlocked (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1)
FAIL ();
CHK_FAIL_END
#endif
lseek (fileno (stdin), 0, SEEK_SET);
if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1

View file

@ -98,6 +98,27 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
return __fgets_alias (__s, __n, __stream);
}
extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;
extern size_t __REDIRECT (__fread_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
fread) __wur;
__extern_always_inline __wur size_t
fread (void *__restrict __ptr, size_t __size, size_t __n,
FILE *__restrict __stream)
{
if (__bos0 (__ptr) != (size_t) -1
&& (!__builtin_constant_p (__size)
|| !__builtin_constant_p (__n)
|| (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))
|| __size * __n > __bos0 (__ptr)))
return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
return __fread_alias (__ptr, __size, __n, __stream);
}
#ifdef __USE_GNU
extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
int __n, FILE *__restrict __stream) __wur;
@ -114,3 +135,49 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
return __fgets_unlocked_alias (__s, __n, __stream);
}
#endif
#ifdef __USE_MISC
# undef fread_unlocked
extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;
extern size_t __REDIRECT (__fread_unlocked_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
fread_unlocked) __wur;
__extern_always_inline __wur size_t
fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
FILE *__restrict __stream)
{
if (__bos0 (__ptr) != (size_t) -1
&& (!__builtin_constant_p (__size)
|| !__builtin_constant_p (__n)
|| (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))
|| __size * __n > __bos0 (__ptr)))
return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, __stream);
# ifdef __USE_EXTERN_INLINES
if (__builtin_constant_p (__size)
&& __builtin_constant_p (__n)
&& (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2))
&& __size * __n <= 8)
{
size_t __cnt = __size * __n;
char *__cptr = (char *) __ptr;
if (__cnt == 0)
return 0;
for (; __cnt > 0; --__cnt)
{
int __c = _IO_getc_unlocked (__stream);
if (__c == EOF)
break;
*__cptr++ = __c;
}
return (__cptr - (char *) __ptr) / __size;
}
# endif
return __fread_unlocked_alias (__ptr, __size, __n, __stream);
}
#endif