]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make this test much more independent of glibc, and update outputs
authorJulian Seward <jseward@acm.org>
Tue, 17 May 2011 15:36:01 +0000 (15:36 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 17 May 2011 15:36:01 +0000 (15:36 +0000)
accordingly.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11762

exp-sgcheck/tests/bad_percentify.c
exp-sgcheck/tests/bad_percentify.stderr.exp-glibc28-amd64
exp-sgcheck/tests/bad_percentify.stdout.exp

index 2567742c393eb06705bad8aeea03a8fd163527a9..94f5559e1252f36247b9d7502f6e7b5d8e31f897 100644 (file)
    is still in Valgrind. */
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <assert.h>
-#include <string.h>
+#include <stdarg.h>
 
 typedef  unsigned long long int  ULong;
+typedef    signed long long int  Long;
 typedef  unsigned int            UInt;
 typedef  signed int              Int;
-typedef  char             Char;
+typedef  signed char             Char;
+typedef  char                    HChar;
+typedef unsigned long            UWord;
+typedef   signed long            Word;
+
+
+
+typedef  unsigned char  Bool;
+#define  True   ((Bool)1)
+#define  False  ((Bool)0)
+
+#define VG_(_str) VG_##_str
+
+
+/* ---------------------------------------------------------------------
+   vg_sprintf, copied from m_libcprint.c
+   ------------------------------------------------------------------ */
+UInt
+VG_(debugLog_vprintf) ( 
+   void(*send)(HChar,void*), 
+   void* send_arg2,
+   const HChar* format, 
+   va_list vargs
+                        );
+
+/* ---------------------------------------------------------------------
+   printf() and friends
+   ------------------------------------------------------------------ */
+typedef
+   struct { Int fd; Bool is_socket; }
+   OutputSink;
+
+
+OutputSink VG_(log_output_sink) = {  2, False }; /* 2 = stderr */
+/* Do the low-level send of a message to the logging sink. */
+static
+void send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes )
+{
+   fwrite(msg, 1, nbytes, stdout);
+   fflush(stdout);
+}
+
+
+/* --------- printf --------- */
+
+typedef 
+   struct {
+      HChar       buf[512];
+      Int         buf_used;
+      OutputSink* sink;
+   } 
+   printf_buf_t;
+
+// Adds a single char to the buffer.  When the buffer gets sufficiently
+// full, we write its contents to the logging sink.
+static void add_to__printf_buf ( HChar c, void *p )
+{
+   printf_buf_t *b = (printf_buf_t *)p;
+   
+   if (b->buf_used > sizeof(b->buf) - 2 ) {
+      send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
+      b->buf_used = 0;
+   }
+   b->buf[b->buf_used++] = c;
+   b->buf[b->buf_used]   = 0;
+   assert(b->buf_used < sizeof(b->buf));
+}
+
+__attribute__((noinline))
+static UInt vprintf_to_buf ( printf_buf_t* b,
+                             const HChar *format, va_list vargs )
+{
+   UInt ret = 0;
+   if (b->sink->fd >= 0 || b->sink->fd == -2) {
+      ret = VG_(debugLog_vprintf) 
+               ( add_to__printf_buf, b, format, vargs );
+   }
+   return ret;
+}
+
+__attribute__((noinline))
+static UInt vprintf_WRK ( OutputSink* sink,
+                          const HChar *format, va_list vargs )
+{
+   printf_buf_t myprintf_buf
+      = { "", 0, sink };
+   UInt ret
+      = vprintf_to_buf(&myprintf_buf, format, vargs);
+   // Write out any chars left in the buffer.
+   if (myprintf_buf.buf_used > 0) {
+      send_bytes_to_logging_sink( myprintf_buf.sink,
+                                  myprintf_buf.buf,
+                                  myprintf_buf.buf_used );
+   }
+   return ret;
+}
+
+__attribute__((noinline))
+UInt VG_(vprintf) ( const HChar *format, va_list vargs )
+{
+   return vprintf_WRK( &VG_(log_output_sink), format, vargs );
+}
+
+__attribute__((noinline))
+UInt VG_(printf) ( const HChar *format, ... )
+{
+   UInt ret;
+   va_list vargs;
+   va_start(vargs, format);
+   ret = VG_(vprintf)(format, vargs);
+   va_end(vargs);
+   return ret;
+}
+
+static Bool toBool ( Int x ) {
+   Int r = (x == 0) ? False : True;
+   return (Bool)r;
+}
+
+__attribute__((noinline))
+static Int local_strlen ( const HChar* str )
+{
+   Int i = 0;
+   while (str[i] != 0) i++;
+   return i;
+}
+
+__attribute__((noinline))
+static HChar local_toupper ( HChar c )
+{
+   if (c >= 'a' && c <= 'z')
+      return c + ('A' - 'a'); 
+   else
+      return c;
+}
+
+
+/*------------------------------------------------------------*/
+/*--- A simple, generic, vprintf implementation.           ---*/
+/*------------------------------------------------------------*/
+
+/* -----------------------------------------------
+   Distantly derived from:
+
+      vprintf replacement for Checker.
+      Copyright 1993, 1994, 1995 Tristan Gingold
+      Written September 1993 Tristan Gingold
+      Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
+
+   (Checker itself was GPL'd.)
+   ----------------------------------------------- */
+
+/* Some flags.  */
+#define VG_MSG_SIGNED    1 /* The value is signed. */
+#define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
+#define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
+#define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
+#define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
+#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
+
+/* Copy a string into the buffer. */
+static __attribute__((noinline))
+UInt myvprintf_str ( void(*send)(HChar,void*),
+                     void* send_arg2,
+                     Int flags, 
+                     Int width, 
+                     HChar* str, 
+                     Bool capitalise )
+{
+#  define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
+   UInt ret = 0;
+   Int i, extra;
+   Int len = local_strlen(str);
+
+   if (width == 0) {
+      ret += len;
+      for (i = 0; i < len; i++)
+          send(MAYBE_TOUPPER(str[i]), send_arg2);
+      return ret;
+   }
+
+   if (len > width) {
+      ret += width;
+      for (i = 0; i < width; i++)
+         send(MAYBE_TOUPPER(str[i]), send_arg2);
+      return ret;
+   }
+
+   extra = width - len;
+   if (flags & VG_MSG_LJUSTIFY) {
+      ret += extra;
+      for (i = 0; i < extra; i++)
+         send(' ', send_arg2);
+   }
+   ret += len;
+   for (i = 0; i < len; i++)
+      send(MAYBE_TOUPPER(str[i]), send_arg2);
+   if (!(flags & VG_MSG_LJUSTIFY)) {
+      ret += extra;
+      for (i = 0; i < extra; i++)
+         send(' ', send_arg2);
+   }
+
+#  undef MAYBE_TOUPPER
+   return ret;
+}
+
+
+/* Copy a string into the buffer, escaping bad XML chars. */
+static 
+UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
+                                    void* send_arg2,
+                                    HChar* str )
+{
+   UInt   ret = 0;
+   Int    i;
+   Int    len = local_strlen(str);
+   HChar* alt;
+
+   for (i = 0; i < len; i++) {
+      switch (str[i]) {
+         case '&': alt = "&amp;"; break;
+         case '<': alt = "&lt;"; break;
+         case '>': alt = "&gt;"; break;
+         default:  alt = NULL;
+      }
+
+      if (alt) {
+         while (*alt) {
+            send(*alt, send_arg2);
+            ret++;
+            alt++;
+         }
+      } else {
+         send(str[i], send_arg2);
+         ret++;
+      }
+   }
+
+   return ret;
+}
+
+
+/* Write P into the buffer according to these args:
+ *  If SIGN is true, p is a signed.
+ *  BASE is the base.
+ *  If WITH_ZERO is true, '0' must be added.
+ *  WIDTH is the width of the field.
+ */
+static 
+UInt myvprintf_int64 ( void(*send)(HChar,void*), 
+                       void* send_arg2,
+                       Int flags, 
+                       Int base, 
+                       Int width, 
+                       Bool capitalised,
+                       ULong p )
+{
+   HChar  buf[40];
+   Int    ind = 0;
+   Int    i, nc = 0;
+   Bool   neg = False;
+   HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
+   UInt   ret = 0;
+
+   if (base < 2 || base > 16)
+      return ret;
+   if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
+      p   = - (Long)p;
+      neg = True;
+   }
+
+   if (p == 0)
+      buf[ind++] = '0';
+   else {
+      while (p > 0) {
+         if (flags & VG_MSG_COMMA && 10 == base &&
+             0 == (ind-nc) % 3 && 0 != ind) 
+         {
+            buf[ind++] = ',';
+            nc++;
+         }
+         buf[ind++] = digits[p % base];
+         p /= base;
+      }
+   }
+
+   if (neg)
+      buf[ind++] = '-';
+
+   if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
+      for(; ind < width; ind++) {
+         /* assert(ind < 39); */
+         if (ind > 39) {
+            buf[39] = 0;
+            break;
+         }
+         buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
+      }
+   }
+
+   /* Reverse copy to buffer.  */
+   ret += ind;
+   for (i = ind -1; i >= 0; i--) {
+      send(buf[i], send_arg2);
+   }
+   if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
+      for(; ind < width; ind++) {
+         ret++;
+         /* Never pad with zeroes on RHS -- changes the value! */
+         send(' ', send_arg2);
+      }
+   }
+   return ret;
+}
+
+
+/* A simple vprintf().  */
+/* EXPORTED */
+__attribute__((noinline))
+UInt
+VG_(debugLog_vprintf) ( 
+   void(*send)(HChar,void*), 
+   void* send_arg2,
+   const HChar* format, 
+   va_list vargs
+)
+{
+   UInt ret = 0;
+   Int  i;
+   Int  flags;
+   Int  width;
+   Int  n_ls = 0;
+   Bool is_long, caps;
+
+   /* We assume that vargs has already been initialised by the 
+      caller, using va_start, and that the caller will similarly
+      clean up with va_end.
+   */
+
+   for (i = 0; format[i] != 0; i++) {
+      if (format[i] != '%') {
+         send(format[i], send_arg2);
+         ret++;
+         continue;
+      }
+      i++;
+      /* A '%' has been found.  Ignore a trailing %. */
+      if (format[i] == 0)
+         break;
+      if (format[i] == '%') {
+         /* '%%' is replaced by '%'. */
+         send('%', send_arg2);
+         ret++;
+         continue;
+      }
+      flags = 0;
+      n_ls  = 0;
+      width = 0; /* length of the field. */
+      while (1) {
+         switch (format[i]) {
+         case '(':
+            flags |= VG_MSG_PAREN;
+            break;
+         case ',':
+         case '\'':
+            /* If ',' or '\'' follows '%', commas will be inserted. */
+            flags |= VG_MSG_COMMA;
+            break;
+         case '-':
+            /* If '-' follows '%', justify on the left. */
+            flags |= VG_MSG_LJUSTIFY;
+            break;
+         case '0':
+            /* If '0' follows '%', pads will be inserted. */
+            flags |= VG_MSG_ZJUSTIFY;
+            break;
+         case '#':
+            /* If '#' follows '%', alternative format will be used. */
+            flags |= VG_MSG_ALTFORMAT;
+            break;
+         default:
+            goto parse_fieldwidth;
+         }
+         i++;
+      }
+     parse_fieldwidth:
+      /* Compute the field length. */
+      while (format[i] >= '0' && format[i] <= '9') {
+         width *= 10;
+         width += format[i++] - '0';
+      }
+      while (format[i] == 'l') {
+         i++;
+         n_ls++;
+      }
+
+      //   %d means print a 32-bit integer.
+      //  %ld means print a word-size integer.
+      // %lld means print a 64-bit integer.
+      if      (0 == n_ls) { is_long = False; }
+      else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
+      else                { is_long = True; }
+
+      switch (format[i]) {
+         case 'o': /* %o */
+            if (flags & VG_MSG_ALTFORMAT) {
+               ret += 2;
+               send('0',send_arg2);
+            }
+            if (is_long)
+               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
+                                      (ULong)(va_arg (vargs, ULong)));
+            else
+               ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
+                                      (ULong)(va_arg (vargs, UInt)));
+            break;
+         case 'd': /* %d */
+            flags |= VG_MSG_SIGNED;
+            if (is_long)
+               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
+                                      (ULong)(va_arg (vargs, Long)));
+            else
+               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
+                                      (ULong)(va_arg (vargs, Int)));
+            break;
+         case 'u': /* %u */
+            if (is_long)
+               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
+                                      (ULong)(va_arg (vargs, ULong)));
+            else
+               ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
+                                      (ULong)(va_arg (vargs, UInt)));
+            break;
+         case 'p': /* %p */
+            ret += 2;
+            send('0',send_arg2);
+            send('x',send_arg2);
+            ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
+                                   (ULong)((UWord)va_arg (vargs, void *)));
+            break;
+         case 'x': /* %x */
+         case 'X': /* %X */
+            caps = toBool(format[i] == 'X');
+            if (flags & VG_MSG_ALTFORMAT) {
+               ret += 2;
+               send('0',send_arg2);
+               send('x',send_arg2);
+            }
+            if (is_long)
+               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
+                                      (ULong)(va_arg (vargs, ULong)));
+            else
+               ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
+                                      (ULong)(va_arg (vargs, UInt)));
+            break;
+         case 'c': /* %c */
+            ret++;
+            send(va_arg (vargs, int), send_arg2);
+            break;
+         case 's': case 'S': { /* %s */
+            char *str = va_arg (vargs, char *);
+            if (str == (char*) 0) str = "(null)";
+            ret += myvprintf_str(send, send_arg2, 
+                                 flags, width, str, format[i]=='S');
+            break;
+         }
+         case 't': { /* %t, like %s but escaping chars for XML safety */
+            /* Note: simplistic; ignores field width and flags */
+            char *str = va_arg (vargs, char *);
+            if (str == (char*) 0) str = "(null)";
+            ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
+            break;
+         }
+
+//         case 'y': { /* %y - print symbol */
+//            Char buf[100];
+//            Char *cp = buf;
+//            Addr a = va_arg(vargs, Addr);
+//
+//            if (flags & VG_MSG_PAREN)
+//               *cp++ = '(';
+//            if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
+//               if (flags & VG_MSG_PAREN) {
+//                  cp += local_strlen(cp);
+//                  *cp++ = ')';
+//                  *cp = '\0';
+//               }
+//               ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
+//            }
+//            break;
+//         }
+         default:
+            break;
+      }
+   }
+   return ret;
+}
+
+
+static void add_to__sprintf_buf ( HChar c, void *p )
+{
+   HChar** b = p;
+   *(*b)++ = c;
+}
+
+UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
+{
+   Int ret;
+   HChar* sprintf_ptr = buf;
+
+   ret = VG_(debugLog_vprintf) 
+            ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
+   add_to__sprintf_buf('\0', &sprintf_ptr);
+
+   assert(local_strlen(buf) == ret);
+
+   return ret;
+}
+
+UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
+{
+   UInt ret;
+   va_list vargs;
+   va_start(vargs,format);
+   ret = VG_(vsprintf)(buf, format, vargs);
+   va_end(vargs);
+   return ret;
+}
+
+
 
 /* ---------------------------------------------------------------------
    percentify()
@@ -21,25 +553,26 @@ typedef  char             Char;
 
 // Percentify n/m with d decimal places.  Includes the '%' symbol at the end.
 // Right justifies in 'buf'.
-void VG_percentify(ULong n, ULong m, UInt d, Int n_buf, char buf[]) 
+__attribute__((noinline))
+void VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[]) 
 {
    Int i, len, space;
    ULong p1;
-   Char fmt[32];
+   HChar fmt[32];
 
    if (m == 0) {
       // Have to generate the format string in order to be flexible about
       // the width of the field.
-      sprintf(fmt, "%%-%ds", n_buf);
+      VG_(sprintf)(fmt, "%%-%ds", n_buf);
       // fmt is now "%<n_buf>s" where <d> is 1,2,3...
-      sprintf(buf, fmt, "--%");
+      VG_(sprintf)(buf, fmt, "--%");
       return;
    }
    
    p1 = (100*n) / m;
     
    if (d == 0) {
-      sprintf(buf, "%lld%%", p1);
+      VG_(sprintf)(buf, "%lld%%", p1);
    } else {
       ULong p2;
       UInt  ex;
@@ -53,12 +586,12 @@ void VG_percentify(ULong n, ULong m, UInt d, Int n_buf, char buf[])
       p2 = ((100*n*ex) / m) % ex;
       // Have to generate the format string in order to be flexible about
       // the width of the post-decimal-point part.
-      sprintf(fmt, "%%lld.%%0%dlld%%%%", d);
+      VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
       // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
-      sprintf(buf, fmt, p1, p2);
+      VG_(sprintf)(buf, fmt, p1, p2);
    }
 
-   len = strlen(buf);
+   len = local_strlen(buf);
    space = n_buf - len;
    if (space < 0) space = 0;     /* Allow for v. small field_width */
    i = len;
@@ -79,23 +612,24 @@ static UInt n_SP_updates_fast            = 0;
 static UInt n_SP_updates_generic_known   = 0;
 static UInt n_SP_updates_generic_unknown = 0;
 
+__attribute__((noinline))
 void VG_print_translation_stats ( void )
 {
-   Char buf[6];
+   HChar buf[6];
    UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known
                                          + n_SP_updates_generic_unknown;
    VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf);
-   printf(
+   VG_(printf)(
       "translate:            fast SP updates identified: %'u (%s)\n",
       n_SP_updates_fast, buf );
 
    VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf);
-   printf(
+   VG_(printf)(
       "translate:   generic_known SP updates identified: %'u (%s)\n",
       n_SP_updates_generic_known, buf );
 
    VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf);
-   printf(
+   VG_(printf)(
       "translate: generic_unknown SP updates identified: %'u (%s)\n",
       n_SP_updates_generic_unknown, buf );
 }
index b647e4a4041958dc5dc0d3b2fde171ba4ddd45e2..eeb4efadc4b00ba86130f42f61802bf86ae2189b 100644 (file)
@@ -1,33 +1,31 @@
+exp-sgcheck, a stack and global array overrun detector
 
 Invalid read of size 1
-   at 0x........: strlen (h_intercepts.c:...)
-   by 0x........: ...
-   by 0x........: ...
-   by 0x........: VG_print_translation_stats (bad_percentify.c:88)
-   by 0x........: main (bad_percentify.c:107)
+   at 0x........: local_strlen (bad_percentify.c:138)
+   by 0x........: VG_vsprintf (bad_percentify.c:531)
+   by 0x........: VG_sprintf (bad_percentify.c:541)
+   by 0x........: VG_percentify (bad_percentify.c:568)
+   by 0x........: VG_print_translation_stats (bad_percentify.c:621)
+   by 0x........: main (bad_percentify.c:641)
  Address 0x........ expected vs actual:
- Expected: stack array "buf" in frame 3 back from here
+ Expected: stack array "buf" of size 6 in frame 4 back from here
  Actual:   unknown
+ Actual:   is 0 after Expected
 
 Invalid read of size 1
-   at 0x........: strlen (h_intercepts.c:...)
-   by 0x........: ...
-   by 0x........: ...
-   by 0x........: VG_print_translation_stats (bad_percentify.c:93)
-   by 0x........: main (bad_percentify.c:107)
+   at 0x........: local_strlen (bad_percentify.c:138)
+   by 0x........: myvprintf_str (bad_percentify.c:187)
+   by 0x........: VG_debugLog_vprintf (bad_percentify.c:479)
+   by 0x........: vprintf_to_buf (bad_percentify.c:89)
+   by 0x........: vprintf_WRK (bad_percentify.c:102)
+   by 0x........: VG_vprintf (bad_percentify.c:115)
+   by 0x........: VG_printf (bad_percentify.c:124)
+   by 0x........: VG_print_translation_stats (bad_percentify.c:622)
+   by 0x........: main (bad_percentify.c:641)
  Address 0x........ expected vs actual:
- Expected: stack array "buf" in frame 3 back from here
- Actual:   unknown
-
-Invalid read of size 1
-   at 0x........: strlen (h_intercepts.c:...)
-   by 0x........: ...
-   by 0x........: ...
-   by 0x........: VG_print_translation_stats (bad_percentify.c:98)
-   by 0x........: main (bad_percentify.c:107)
- Address 0x........ expected vs actual:
- Expected: stack array "buf" in frame 3 back from here
+ Expected: stack array "buf" of size 6 in frame 7 back from here
  Actual:   unknown
+ Actual:   is 0 after Expected
 
 
-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
+ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 0 from 0)
index fd99c2c17665fe1ad90d1a7d45c10304b8b8f706..a4ab2ff3e92cb8bdc8930aa33a05534616aee9ee 100644 (file)
@@ -1,3 +1,3 @@
-translate:            fast SP updates identified: 0 (--%   )
-translate:   generic_known SP updates identified: 0 (--%   )
-translate: generic_unknown SP updates identified: 0 (--%   )
+translate:            fast SP updates identified: 0 (   --%)
+translate:   generic_known SP updates identified: 0 (   --%)
+translate: generic_unknown SP updates identified: 0 (   --%)