This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: better cpplex.c patch
- To: law at cygnus dot com
- Subject: Re: PATCH: better cpplex.c patch
- From: Greg McGary <greg at mcgary dot org>
- Date: 14 Sep 2000 11:47:02 -0700
- Cc: gcc-patches at gcc dot gnu dot org
- References: <4749.968946545@upchuck>
Jeffrey A Law <law@cygnus.com> writes:
> The whole patch please -- including Makefile.in changes, the ChangeLog entry, etc.
2000-09-14 Greg McGary <greg@mcgary.org>
include:
* bounded-ptr.h: New file.
gcc:
* Makefile.in (BOUNDED_PTR_H): New variable.
(ggc-page.o, cpplex.o): Depend on $(BOUNDED_PTR_H).
* cpplex.c (_cpp_expand_name_space): Use RELOCATE_POINTER_INCR_HIGH.
(parse_number, parse_string, save_comment): Use SET_BOUNDS.
* ggc-page.c (ggc_alloc): Use SET_BOUNDS.
* ginclude/bounded-ptr.h: New file.
Index: gcc/Makefile.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Makefile.in,v
retrieving revision 1.511
diff -u -p -r1.511 Makefile.in
--- Makefile.in 2000/09/11 01:50:45 1.511
+++ Makefile.in 2000/09/14 09:04:14
@@ -229,6 +229,7 @@ SYSTEM_HEADER_DIR = /usr/include
# Where to find some libiberty headers.
HASHTAB_H = $(srcdir)/../include/hashtab.h
OBSTACK_H = $(srcdir)/../include/obstack.h
+BOUNDED_PTR_H = $(srcdir)/../include/bounded-ptr.h
SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
# Default cross SYSTEM_HEADER_DIR, to be overridden by targets.
@@ -1209,7 +1210,7 @@ ggc-simple.o: ggc-simple.c $(CONFIG_H) $
$(GGC_H) varray.h $(TIMEVAR_H)
ggc-page.o: ggc-page.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h toplev.h \
- $(GGC_H) varray.h $(TIMEVAR_H)
+ $(GGC_H) varray.h $(TIMEVAR_H) $(BOUNDED_PTR_H)
ggc-none.o: ggc-none.c $(CONFIG_H) $(RTL_H) $(GGC_H)
@@ -1809,7 +1810,7 @@ cppmain.o: cppmain.c $(CONFIG_H) cppli
cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS) defaults.h
-cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS)
+cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) $(BOUNDED_PTR_H)
cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
Index: gcc/cpplex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cpplex.c,v
retrieving revision 1.95
diff -u -p -r1.95 cpplex.c
--- cpplex.c 2000/09/12 03:42:29 1.95
+++ cpplex.c 2000/09/14 09:04:16
@@ -44,6 +44,7 @@ o Correct pastability test for CPP_NAME
#include "cpplib.h"
#include "cpphash.h"
#include "symcat.h"
+#include "bounded-ptr.h"
static const cpp_token placemarker_token = {0, 0, CPP_PLACEMARKER, 0 UNION_INIT_ZERO};
static const cpp_token eof_token = {0, 0, CPP_EOF, 0 UNION_INIT_ZERO};
@@ -450,13 +451,19 @@ _cpp_expand_name_space (list, len)
list->namebuf = (unsigned char *) xrealloc (list->namebuf, list->name_cap);
/* Fix up token text pointers. */
- if (list->namebuf != old_namebuf)
+ if (list->namebuf != old_namebuf || __BOUNDED_POINTERS__)
{
+ long disp = list->namebuf - old_namebuf;
unsigned int i;
for (i = 0; i < list->tokens_used; i++)
if (TOKEN_SPELL (&list->tokens[i]) == SPELL_STRING)
- list->tokens[i].val.str.text += (list->namebuf - old_namebuf);
+ /* The token with zero length is the one on whose behalf
+ we are expanding the namebuf, so be sure to increment
+ its high bound to reflect the added space. No other
+ tokens should expand their high bounds. */
+ RELOCATE_POINTER_INCR_HIGH (list->tokens[i].val.str.text, disp,
+ (list->tokens[i].val.str.len ? 0 : len));
}
}
@@ -1049,6 +1056,7 @@ parse_number (pfile, list, name)
out:
buffer->cur = cur;
name->len = namebuf - name->text;
+ SET_BOUNDS (name->text, name->len);
list->name_used = namebuf - list->namebuf;
}
@@ -1199,6 +1207,7 @@ parse_string (pfile, list, token, termin
out:
buffer->cur = cur;
name->len = namebuf - name->text;
+ SET_BOUNDS (name->text, name->len);
list->name_used = namebuf - list->namebuf;
if (null_count > 0)
@@ -1227,6 +1236,7 @@ save_comment (list, token, from, len, ty
_cpp_expand_name_space (list, len);
INIT_TOKEN_STR (list, token);
+ SET_BOUNDS (token->val.str.text, len);
token->type = CPP_COMMENT;
token->val.str.len = len;
Index: gcc/ggc-page.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ggc-page.c,v
retrieving revision 1.30
diff -u -p -r1.30 ggc-page.c
--- ggc-page.c 2000/08/29 20:57:11 1.30
+++ ggc-page.c 2000/09/14 09:04:17
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "ggc.h"
#include "timevar.h"
+#include "bounded-ptr.h"
#ifdef HAVE_MMAP_ANYWHERE
#include <sys/mman.h>
@@ -725,6 +726,7 @@ ggc_alloc (size)
the end. */
memset (result, 0xaf, 1 << order);
#endif
+ SET_BOUNDS (result, size);
/* Keep track of how many bytes are being allocated. This
information is used in deciding when to collect. */
Index: include/bounded-ptr.h
===================================================================
RCS file: bounded-ptr.h
diff -N bounded-ptr.h
--- /dev/null Tue May 5 13:32:27 1998
+++ bounded-ptr.h Thu Sep 14 11:44:30 2000
@@ -0,0 +1,59 @@
+/* Header file for modules that link with gcc.c
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Greg McGary <greg@mcgary.org>
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _bounded_ptr_wrapper_h_
+#define _bounded_ptr_wrapper_h_
+
+#if __BOUNDED_POINTERS__
+/* Some crufty cpps choke on non-standard directives, even within the
+ untaken side of a conditional. They can be foold by indenting '#'. */
+ #include_next <bounded-ptr.h>
+#else
+
+/* Ensure that we can use __BOUNDED_POINTERS__ in C expressions. */
+# undef __BOUNDED_POINTERS__
+# define __BOUNDED_POINTERS__ 0
+
+/* Do nothing if not compiling with -fbounded-pointers. */
+
+# define BOUNDS_VIOLATED
+# define CHECK_BOUNDS_LOW(PTR) (PTR)
+# define CHECK_BOUNDS_HIGH(PTR) (PTR)
+# define CHECK_1(PTR) (PTR)
+# define CHECK_1_NULL_OK(PTR) (PTR)
+# define CHECK_N(ARG, N) (PTR)
+# define CHECK_N_NULL_OK(ARG, N) (PTR)
+# define CHECK_STRING(PTR) (PTR)
+# define CHECK_SIGSET(SET) (SET)
+# define CHECK_SIGSET_NULL_OK(SET) (SET)
+# define CHECK_IOCTL(ARG, CMD) (PTR)
+# define CHECK_FCNTL(ARG, CMD) (PTR)
+# define CHECK_N_PAGES(ARG, NBYTES) (PTR)
+# define SET_BOUNDS(PTR, N)
+# define BOUNDED_N(PTR, N) (PTR)
+# define BOUNDED_1(PTR) (PTR)
+# define RELOCATE_POINTER(PTR, DISP) ((PTR) += (DISP))
+# define RELOCATE_POINTER_INCR_HIGH(PTR, DISP, INCR) ((PTR) += (DISP))
+# define RELOCATE_POINTER_SET_HIGH(PTR, DISP, LENGTH) ((PTR) += (DISP))
+
+#endif /* __BOUNDED_POINTERS__ */
+
+#endif /* _bounded_ptr_wrapper_h_ */
Index: gcc/ginclude/bounded-ptr.h
===================================================================
RCS file: bounded-ptr.h
diff -N bounded-ptr.h
--- /dev/null Tue May 5 13:32:27 1998
+++ bounded-ptr.h Thu Sep 14 11:44:30 2000
@@ -0,0 +1,160 @@
+/* Header file for modules that link with gcc.c
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Greg McGary <greg@mcgary.org>
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _bounded_ptr_h_
+#define _bounded_ptr_h_
+
+#if __BOUNDED_POINTERS__
+
+# define BOUNDS_VIOLATED (__builtin_trap (), 0)
+
+/* Verify that pointer's value >= low. Return pointer value. */
+# define CHECK_BOUNDS_LOW(PTR) \
+ (((__ptrvalue (PTR) < __ptrlow (PTR)) && BOUNDS_VIOLATED), \
+ __ptrvalue (PTR))
+
+/* Verify that pointer's value < high. Return pointer value. */
+# define CHECK_BOUNDS_HIGH(PTR) \
+ (((__ptrvalue (PTR) > __ptrhigh (PTR)) && BOUNDS_VIOLATED), \
+ __ptrvalue (PTR))
+
+/* Check both bounds if COND is nonzero. Return pointer value. */
+# define _CHECK_N(PTR, N, COND) \
+ (((COND) \
+ && (__ptrvalue (PTR) < __ptrlow (PTR) \
+ || __ptrvalue (PTR) + (N) > __ptrhigh (PTR)) \
+ && BOUNDS_VIOLATED), \
+ __ptrvalue (PTR))
+
+/* This is provided by the bounded-pointer version of glibc. */
+extern void *__unbounded __ubp_memchr (const void *__unbounded, int, unsigned);
+
+/* Verify that a NUL-terminator occurs within the bounds of the string. */
+# define _CHECK_STRING(PTR, COND) \
+ (((COND) \
+ && (__ptrvalue (PTR) < __ptrlow (PTR) \
+ || !__ubp_memchr (__ptrvalue (PTR), '\0', \
+ (__ptrhigh (PTR) - __ptrvalue (PTR)))) \
+ && BOUNDS_VIOLATED), \
+ __ptrvalue (PTR))
+
+/* Check bounds of a pointer seated to an array of N objects. */
+# define CHECK_N(PTR, N) _CHECK_N ((PTR), (N), 1)
+/* Same as CHECK_N, but tolerate PTR == NULL. */
+# define CHECK_N_NULL_OK(PTR, N) _CHECK_N ((PTR), (N), __ptrvalue (PTR))
+
+/* Check for NUL-terminator within string's bounds. */
+# define CHECK_STRING(PTR) _CHECK_STRING ((PTR), 1)
+/* Same as CHECK_STRING, but tolerate PTR == NULL. */
+# define CHECK_STRING_NULL_OK(PTR) _CHECK_STRING ((PTR), __ptrvalue (PTR))
+
+/* Set the bounds of a bounded pointer so that it satisfies CHECK_N (PTR, N). */
+# define SET_BOUNDS(PTR, N) \
+ (__ptrlow (PTR) = __ptrvalue (PTR), __ptrhigh (PTR) = __ptrvalue (PTR) + (N))
+
+/* Return a bounded pointer with value PTR that satisfies CHECK_N (PTR, N). */
+# define BOUNDED_N(PTR, N) \
+ ({ __typeof (PTR) __bounded _p_; \
+ __ptrvalue _p_ = __ptrlow _p_ = __ptrvalue (PTR); \
+ __ptrhigh _p_ = __ptrvalue _p_ + (N); \
+ _p_; })
+
+/* When a buffer is expanded with realloc, and there are other pointers
+ into the old buffer, they must be relocated to the new buffer. */
+
+/* Relocate the pointer and leave the width of its bounds unchanged. */
+# define RELOCATE_POINTER(PTR, DISP) RELOCATE_POINTER_INCR_HIGH ((PTR), (DISP), 0)
+
+/* Relocate the pointer and increment the width of its bounds. */
+# define RELOCATE_POINTER_INCR_HIGH(PTR, DISP, INCR) \
+ (__ptrlow (PTR) += (DISP), __ptrhigh (PTR) += ((DISP) + (INCR)), \
+ __ptrvalue (PTR) += (DISP))
+
+/* Relocate the pointer and reset the width of its bounds. */
+# define RELOCATE_POINTER_SET_HIGH(PTR, DISP, LENGTH) \
+ (__ptrlow (PTR) += (DISP), __ptrhigh (PTR) = (__ptrlow (PTR) + (LENGTH)), \
+ __ptrvalue (PTR) += (DISP))
+
+/* Check bounds of signal syscall args with type sigset_t. */
+# define CHECK_SIGSET(SET) CHECK_N ((SET), _NSIG / (8 * sizeof *(SET)))
+/* Same as CHECK_SIGSET, but tolerate SET == NULL. */
+# define CHECK_SIGSET_NULL_OK(SET) CHECK_N_NULL_OK ((SET), _NSIG / (8 * sizeof *(SET)))
+
+# if defined (_IOC_SIZESHIFT) && defined (_IOC_SIZEBITS)
+/* Extract the size of the ioctl data and check its bounds. */
+# define CHECK_IOCTL(PTR, CMD) \
+ CHECK_N ((const char *) (PTR), \
+ (((CMD) >> _IOC_SIZESHIFT) & ((1 << _IOC_SIZEBITS) - 1)))
+# else
+/* We don't know the size of the ioctl data, so the best we can do
+ is check that the first byte is within bounds. */
+# define CHECK_IOCTL(PTR, CMD) CHECK_1 ((const char *) PTR)
+# endif
+
+/* Check bounds of `struct flock *' for the locking fcntl commands. */
+# define CHECK_FCNTL(PTR, CMD) \
+ (((CMD) == F_GETLK || (CMD) == F_SETLK || (CMD) == F_SETLKW) \
+ ? CHECK_1 ((struct flock *) PTR) : (unsigned long) (PTR))
+
+# define CHECK_N_PAGES(PTR, NBYTES) \
+ ({ int _page_size_ = sysconf (_SC_PAGE_SIZE); \
+ CHECK_N ((PTR), ((NBYTES) + _page_size_ - 1) / _page_size_); })
+
+#else /* !__BOUNDED_POINTERS__ */
+
+/* Ensure that we can use __BOUNDED_POINTERS__ in C expressions. */
+# undef __BOUNDED_POINTERS__
+# define __BOUNDED_POINTERS__ 0
+
+/* Do nothing if not compiling with -fbounded-pointers. */
+
+# define BOUNDS_VIOLATED
+# define CHECK_BOUNDS_LOW(PTR) (PTR)
+# define CHECK_BOUNDS_HIGH(PTR) (PTR)
+# define CHECK_N(PTR, N) (PTR)
+# define CHECK_N_NULL_OK(PTR, N) (PTR)
+# define CHECK_STRING(PTR) (PTR)
+
+# define SET_BOUNDS(PTR, N)
+# define BOUNDED_N(PTR, N) (PTR)
+
+# define RELOCATE_POINTER(PTR, DISP) ((PTR) += (DISP))
+# define RELOCATE_POINTER_INCR_HIGH(PTR, DISP, INCR) ((PTR) += (DISP))
+# define RELOCATE_POINTER_SET_HIGH(PTR, DISP, LENGTH) ((PTR) += (DISP))
+
+# define CHECK_SIGSET(SET) (SET)
+# define CHECK_SIGSET_NULL_OK(SET) (SET)
+# define CHECK_IOCTL(PTR, CMD) (PTR)
+# define CHECK_FCNTL(PTR, CMD) (PTR)
+# define CHECK_N_PAGES(PTR, NBYTES) (PTR)
+
+#endif /* !__BOUNDED_POINTERS__ */
+
+/* Some shorthand notations... */
+
+/* Return a bounded pointer with value PTR that satisfies CHECK_1 (PTR). */
+#define BOUNDED_1(PTR) BOUNDED_N (PTR, 1)
+/* Check bounds of a pointer seated to a single object. */
+# define CHECK_1(PTR) CHECK_N ((PTR), 1)
+/* Same as CHECK_1, but tolerate PTR == NULL. */
+# define CHECK_1_NULL_OK(PTR) CHECK_N_NULL_OK ((PTR), 1)
+
+#endif /* _bounded_ptr_h_ */