]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - libiberty/testsuite/test-demangle.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / libiberty / testsuite / test-demangle.c
index dcb27d259d488f256b8f9c9b4e58c57ba90fbcd9..b8024f200f7e4d2edef951c42fa79d02b0ccc7b8 100644 (file)
@@ -1,5 +1,5 @@
 /* Demangler test program,
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    Written by Zack Weinberg <zack@codesourcery.com
 
    This file is part of GNU libiberty.
@@ -32,6 +32,9 @@
 #if HAVE_STDLIB_H
 # include <stdlib.h>
 #endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 struct line
 {
@@ -46,7 +49,7 @@ static unsigned int lineno;
 #define LINELEN 80
 
 static void
-getline(buf)
+get_line(buf)
      struct line *buf;
 {
   char *data = buf->data;
@@ -86,6 +89,50 @@ getline(buf)
   buf->alloced = alloc;
 }
 
+/* If we have mmap() and mprotect(), copy the string S just before a
+   protected page, so that if the demangler runs over the end of the
+   string we'll get a fault, and return the address of the new string.
+   If no mmap, or it fails, or it looks too hard, just return S.  */
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+static const char *
+protect_end (const char * s)
+{
+#if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
+  size_t pagesize = getpagesize();
+  static char * buf;
+  size_t s_len = strlen (s);
+  char * result;
+  
+  /* Don't try if S is too long.  */
+  if (s_len >= pagesize)
+    return s;
+
+  /* Allocate one page of allocated space followed by an unmapped
+     page.  */
+  if (buf == NULL)
+    {
+      buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
+                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+      if (! buf)
+       return s;
+      munmap (buf + pagesize, pagesize);
+    }
+  
+  result = buf + (pagesize - s_len - 1);
+  memcpy (result, s, s_len + 1);
+  return result;
+#else
+  return s;
+#endif
+}
+
 static void
 fail (lineno, opts, in, out, exp)
      int lineno;
@@ -114,6 +161,8 @@ exp: %s\n",
      --is-v3-ctor        Calls is_gnu_v3_mangled_ctor on input; expected
                          output is an integer representing ctor_kind.
      --is-v3-dtor        Likewise, but for dtors.
+     --ret-postfix       Passes the DMGL_RET_POSTFIX option
+     --ret-drop          Passes the DMGL_RET_DROP option
 
    For compatibility, just in case it matters, the options line may be
    empty, to mean --format=auto.  If it doesn't start with --, then it
@@ -129,6 +178,7 @@ main(argc, argv)
   int no_params;
   int is_v3_ctor;
   int is_v3_dtor;
+  int ret_postfix, ret_drop;
   struct line format;
   struct line input;
   struct line expect;
@@ -148,16 +198,22 @@ main(argc, argv)
 
   for (;;)
     {
-      getline (&format);
+      const char *inp;
+      
+      get_line (&format);
       if (feof (stdin))
        break;
 
-      getline (&input);
-      getline (&expect);
+      get_line (&input);
+      get_line (&expect);
+
+      inp = protect_end (input.data);
 
       tests++;
 
       no_params = 0;
+      ret_postfix = 0;
+      ret_drop = 0;
       is_v3_ctor = 0;
       is_v3_dtor = 0;
       if (format.data[0] == '\0')
@@ -212,6 +268,10 @@ main(argc, argv)
                is_v3_ctor = 1;
              else if (strcmp (opt, "--is-v3-dtor") == 0)
                is_v3_dtor = 1;
+             else if (strcmp (opt, "--ret-postfix") == 0)
+               ret_postfix = 1;
+             else if (strcmp (opt, "--ret-drop") == 0)
+               ret_drop = 1;
              else
                {
                  printf ("FAIL at line %d: unrecognized option %s\n",
@@ -232,14 +292,14 @@ main(argc, argv)
            {
              enum gnu_v3_ctor_kinds kc;
 
-             kc = is_gnu_v3_mangled_ctor (input.data);
+             kc = is_gnu_v3_mangled_ctor (inp);
              sprintf (buf, "%d", (int) kc);
            }
          else
            {
              enum gnu_v3_dtor_kinds kd;
 
-             kd = is_gnu_v3_mangled_dtor (input.data);
+             kd = is_gnu_v3_mangled_dtor (inp);
              sprintf (buf, "%d", (int) kd);
            }
 
@@ -254,8 +314,9 @@ main(argc, argv)
 
       cplus_demangle_set_style (style);
 
-      result = cplus_demangle (input.data,
-                              DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES);
+      result = cplus_demangle (inp, (DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES
+                                    | (ret_postfix ? DMGL_RET_POSTFIX : 0)
+                                    | (ret_drop ? DMGL_RET_DROP : 0)));
 
       if (result
          ? strcmp (result, expect.data)
@@ -268,8 +329,8 @@ main(argc, argv)
 
       if (no_params)
        {
-         getline (&expect);
-         result = cplus_demangle (input.data, DMGL_ANSI|DMGL_TYPES);
+         get_line (&expect);
+         result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
 
          if (result
              ? strcmp (result, expect.data)