]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Ability to add suppressions based on source file name and line number.
authorIvo Raisr <ivosh@ivosh.net>
Mon, 25 Jun 2018 19:52:08 +0000 (21:52 +0200)
committerIvo Raisr <ivosh@ivosh.net>
Tue, 26 Jun 2018 04:36:12 +0000 (06:36 +0200)
Fixes BZ#390471.
Patch based on work by: Jeff Frontz <jeff.frontz@gmail.com> and Joseph M Link.

12 files changed:
NEWS
coregrind/m_errormgr.c
docs/xml/manual-core.xml
memcheck/tests/Makefile.am
memcheck/tests/suppsrc_lineno.stderr.exp [new file with mode: 0644]
memcheck/tests/suppsrc_lineno.stdout.exp [new file with mode: 0644]
memcheck/tests/suppsrc_lineno.supp [new file with mode: 0644]
memcheck/tests/suppsrc_lineno.vgtest [new file with mode: 0644]
memcheck/tests/suppsrc_sanlineno.stderr.exp [new file with mode: 0644]
memcheck/tests/suppsrc_sanlineno.stdout.exp [new file with mode: 0644]
memcheck/tests/suppsrc_sanlineno.supp [new file with mode: 0644]
memcheck/tests/suppsrc_sanlineno.vgtest [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 0f150563f21c26f194c0aa6b3d6505b1c226c27c..2e13004e41563e3ecd855c94ee10af7378367068 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ support for X86/macOS 10.13, AMD64/macOS 10.13.
   (e.g. memory leaks) to include file/line info for code that has been
   dlclose'd (or similar). See user manual for more information and
   known limitations.
+* Ability to specify suppressions based on source file name and line number.
 
 * ================== PLATFORM CHANGES =================
 
@@ -105,6 +106,7 @@ where XXXXXX is the bug number as listed below.
 388862  Add replacements for wmemchr and wcsnlen on Linux
 389373  exp-sgcheck the 'impossible' happened as Ist_LoadG is not instrumented
 389065  valgrind meets gcc flag -Wlogical-op
+390471  suppression by specification of source-file line number
 390723  make xtree dump files world wide readable, similar to log files
 391861  Massif Assertion 'n_ips >= 1 && n_ips <= VG_(clo_backtrace_size)'
 392449  callgrind not clearing the number of calls properly
index 38e67699f128ac9a0d9434d77f2a7087ea9006eb..00ffc7ac06935182f2d0778fd8fe71a034e00d90 100644 (file)
@@ -205,7 +205,8 @@ typedef
       NoName,     /* Error case */
       ObjName,    /* Name is of an shared object file. */
       FunName,    /* Name is of a function. */
-      DotDotDot   /* Frame-level wildcard */
+      DotDotDot,  /* Frame-level wildcard */
+      SrcName     /* Name is of a src file. */
    }
    SuppLocTy;
 
@@ -215,6 +216,7 @@ typedef
       Bool      name_is_simple_str; /* True if name is a string without
                                        '?' and '*' wildcard characters. */
       HChar*    name; /* NULL for NoName and DotDotDot */
+      UInt      lineno; /* Valid for SrcName. */
    }
    SuppLoc;
 
@@ -1203,10 +1205,13 @@ static Bool is_simple_str (const HChar *s)
 /* buf contains the raw name of a caller, supposedly either
        fun:some_function_name   or
        obj:some_object_name     or
+       fun:some_file_name       or
+       fun:some_file_name:line# or
        ...
    Set p->ty and p->name accordingly.
    p->name is allocated and set to the string
-   after the descriptor (fun: or obj:) part.
+   after the descriptor (fun:, obj:, or src: san line#) part.
+   p->lineno is set to non-zero if line# specified; 0 otherwise.
    Returns False if failed.
 */
 static Bool setLocationTy ( SuppLoc* p, const HChar *buf )
@@ -1223,6 +1228,19 @@ static Bool setLocationTy ( SuppLoc* p, const HChar *buf )
       p->ty = ObjName;
       return True;
    }
+   if (VG_(strncmp)(buf, "src:", 4) == 0) {
+      p->name = VG_(strdup)("errormgr.sLTy.3", buf+4);
+      p->name_is_simple_str = is_simple_str (p->name);
+      p->ty = SrcName;
+      HChar *s = VG_(strchr)(p->name, ':');
+      if (s != NULL) {
+         *s++ = '\0'; // trim colon
+         p->lineno = (UInt) VG_(strtoll10)(s, NULL);
+      } else {
+         p->lineno = 0;
+      }
+      return True;
+   }
    if (VG_(strcmp)(buf, "...") == 0) {
       p->name = NULL;
       p->name_is_simple_str = False;
@@ -1230,7 +1248,7 @@ static Bool setLocationTy ( SuppLoc* p, const HChar *buf )
       return True;
    }
    VG_(printf)("location should be \"...\", or should start "
-               "with \"fun:\" or \"obj:\"\n");
+               "with \"fun:\", \"obj:\", or \"src:\"\n");
    return False;
 }
 
@@ -1405,7 +1423,7 @@ static void load_one_suppressions_file ( Int clo_suppressions_i )
             break;
          if (!setLocationTy(&(tmp_callers[i]), buf))
             BOMB("location should be \"...\", or should start "
-                 "with \"fun:\" or \"obj:\"");
+                 "with \"fun:\", \"obj:\", or \"src:\"");
          i++;
       }
 
@@ -1421,8 +1439,10 @@ static void load_one_suppressions_file ( Int clo_suppressions_i )
       // level wildcards.
       vg_assert(i > 0); // guaranteed by frame-descriptor reading loop
       for (j = 0; j < i; j++) {
-         if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName)
+         if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName ||
+             tmp_callers[j].ty == SrcName) {
             break;
+         }
          vg_assert(tmp_callers[j].ty == DotDotDot);
       }
       vg_assert(j >= 0 && j <= i);
@@ -1812,7 +1832,8 @@ static Bool supp_pattEQinp ( const void* supplocV, const void* addrV,
 {
    const SuppLoc* supploc = (const SuppLoc*)supplocV; /* PATTERN */
    IPtoFunOrObjCompleter* ip2fo = (IPtoFunOrObjCompleter*)inputCompleterV;
-   HChar* funobj_name; // Fun or Obj name.
+   const HChar* funobjsrc_name; // Fun, Obj, or src file name.
+   UInt src_lineno;
    Bool ret;
 
    expandInput(ip2fo, ixInput);
@@ -1828,27 +1849,42 @@ static Bool supp_pattEQinp ( const void* supplocV, const void* addrV,
             this can't happen. */
          vg_assert(0);
       case ObjName:
-         funobj_name = foComplete(ip2fo, ixInput, False /*needFun*/);
+         funobjsrc_name = foComplete(ip2fo, ixInput, False /*needFun*/);
          break; 
       case FunName:
-         funobj_name = foComplete(ip2fo, ixInput, True /*needFun*/);
+         funobjsrc_name = foComplete(ip2fo, ixInput, True /*needFun*/);
+         break;
+      case SrcName: {
+         const HChar* src_dirname; // placeholder only
+         ret = VG_(get_filename_linenum)(VG_(current_DiEpoch)(),
+               ip2fo->ips[ixInput], &funobjsrc_name, &src_dirname, &src_lineno);
+         if (!ret) {
+            /* No file name found for location so no way this is a match. */
+            return ret;
+         }
          break;
+      }
       default:
         vg_assert(0);
    }
 
-   /* So now we have the function or object name in funobj_name, and
+   /* So now we have the function or object name in funobjsrc_name, and
       the pattern (at the character level) to match against is in
       supploc->name.  Hence (and leading to a re-entrant call of
       VG_(generic_match) if there is a wildcard character): */
    if (supploc->name_is_simple_str)
-      ret = VG_(strcmp) (supploc->name, funobj_name) == 0;
+      ret = VG_(strcmp) (supploc->name, funobjsrc_name) == 0;
    else
-      ret = VG_(string_match)(supploc->name, funobj_name);
+      ret = VG_(string_match)(supploc->name, funobjsrc_name);
+   if (ret && supploc->ty == SrcName && supploc->lineno != 0) {
+      ret = (supploc->lineno == src_lineno);
+   }
    if (DEBUG_ERRORMGR)
-      VG_(printf) ("supp_pattEQinp %s patt %s ixUnput %lu value:%s match:%s\n",
-                   supploc->ty == FunName ? "fun" : "obj",
-                   supploc->name, ixInput, funobj_name,
+      VG_(printf) ("supp_pattEQinp %s patt %s ixInput %lu value:%s (lineno:%u vs %u) match:%s\n",
+                   supploc->ty == FunName ? "fun" : (supploc->ty == SrcName ? "src" : "obj"),
+                   supploc->name, ixInput, funobjsrc_name,
+                   supploc->ty == SrcName ? supploc->lineno : 0,
+                   supploc->ty == SrcName ? src_lineno : 0,
                    ret ? "yes" : "no");
    return ret;
 }
index 48321acd5bd77488818ce0c2c5821a59092ddf16..0e787d75bfd7031029fd1477697d6c1f5363e077 100644 (file)
@@ -460,13 +460,15 @@ tool_name1,tool_name2:suppression_name]]></programlisting>
     the chain of function calls that led to it.  There can be up to 24
     of these lines.</para>
 
-    <para>Locations may be names of either shared objects or
-    functions.  They begin
-    <computeroutput>obj:</computeroutput> and
-    <computeroutput>fun:</computeroutput> respectively.  Function and
-    object names to match against may use the wildcard characters
+    <para>Locations may be names of either shared objects, functions,
+    or source lines.  They begin with
+    <computeroutput>obj:</computeroutput>,
+    <computeroutput>fun:</computeroutput>, or
+    <computeroutput>src:</computeroutput> respectively.  Function,
+    object, and file names to match against may use the wildcard characters
     <computeroutput>*</computeroutput> and
-    <computeroutput>?</computeroutput>.</para>
+    <computeroutput>?</computeroutput>.   Source lines are specified
+    using the form <filename>filename[:lineNumber]</filename>.</para>
 
     <para><command>Important note: </command> C++ function names must be
     <command>mangled</command>.  If you are writing suppressions by
@@ -543,9 +545,23 @@ locations is regrettable, but is about all you can hope for, given that
 the X11 libraries shipped on the Linux distro on which this example
 was made have had their symbol tables removed.</para>
 
+<para>An example of the src: specification, again for the Memcheck tool:</para>
+
+<programlisting><![CDATA[
+{
+  libX11.so.6.2/libX11.so.6.2/libXaw.so.7.0
+  Memcheck:Value4
+  src:valid.c:321
+}]]></programlisting>
+
+<para>This suppresses any size-4 uninitialised-value error which occurs
+at line 321 in <filename>valid.c</filename>.</para>
+
 <para>Although the above two examples do not make this clear, you can
-freely mix <computeroutput>obj:</computeroutput> and
-<computeroutput>fun:</computeroutput> lines in a suppression.</para>
+freely mix <computeroutput>obj:</computeroutput>,
+<computeroutput>fun:</computeroutput>, and
+<computeroutput>src:</computeroutput>
+lines in a suppression.</para>
 
 <para>Finally, here's an example using three frame-level wildcards:</para>
 
index 38b0822cdf270b40202256f4bc58860dce1d210d..84e49405f1b7bd6a7dd682bedd61e208cfb2c5ca 100644 (file)
@@ -276,6 +276,8 @@ EXTRA_DIST = \
        suppfree.stderr.exp suppfree.supp suppfree.vgtest \
        suppfreecollision.stderr.exp suppfreecollision.supp suppfreecollision.vgtest \
        supponlyobj.stderr.exp supponlyobj.supp supponlyobj.vgtest \
+       suppsrc_lineno.stderr.exp suppsrc_lineno.stdout.exp suppsrc_lineno.vgtest \
+       suppsrc_sanlineno.stderr.exp suppsrc_sanlineno.stdout.exp suppsrc_sanlineno.vgtest \
        suppvarinfo5.stderr.exp suppvarinfo5.supp suppvarinfo5.vgtest \
        test-plo-no.vgtest test-plo-no.stdout.exp \
            test-plo-no.stderr.exp-le64 test-plo-no.stderr.exp-le32 \
diff --git a/memcheck/tests/suppsrc_lineno.stderr.exp b/memcheck/tests/suppsrc_lineno.stderr.exp
new file mode 100644 (file)
index 0000000..9ad57cb
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid free() / delete / delete[] / realloc()
+   at 0x........: free (vg_replace_malloc.c:...)
+   ...
+ Address 0x........ is 0 bytes inside a block of size 10 free'd
+   at 0x........: free (vg_replace_malloc.c:...)
+   ...
+ Block was alloc'd at
+   at 0x........: malloc (vg_replace_malloc.c:...)
+   ...
+
diff --git a/memcheck/tests/suppsrc_lineno.stdout.exp b/memcheck/tests/suppsrc_lineno.stdout.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/suppsrc_lineno.supp b/memcheck/tests/suppsrc_lineno.supp
new file mode 100644 (file)
index 0000000..99b6414
--- /dev/null
@@ -0,0 +1,13 @@
+{
+   matching-lineno1
+   Memcheck:Free
+   fun:free
+   src:suppfree.c:6
+}
+
+{
+   non-matching-lineno2
+   Memcheck:Free
+   fun:free
+   src:suppfree.c:20
+}
diff --git a/memcheck/tests/suppsrc_lineno.vgtest b/memcheck/tests/suppsrc_lineno.vgtest
new file mode 100644 (file)
index 0000000..ce6188b
--- /dev/null
@@ -0,0 +1,2 @@
+prog: suppfree
+vgopts: --suppressions=suppsrc_lineno.supp -q
\ No newline at end of file
diff --git a/memcheck/tests/suppsrc_sanlineno.stderr.exp b/memcheck/tests/suppsrc_sanlineno.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/suppsrc_sanlineno.stdout.exp b/memcheck/tests/suppsrc_sanlineno.stdout.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/suppsrc_sanlineno.supp b/memcheck/tests/suppsrc_sanlineno.supp
new file mode 100644 (file)
index 0000000..d92319b
--- /dev/null
@@ -0,0 +1,6 @@
+{
+   matching-san-lineno
+   Memcheck:Free
+   fun:free
+   src:suppfree.c
+}
diff --git a/memcheck/tests/suppsrc_sanlineno.vgtest b/memcheck/tests/suppsrc_sanlineno.vgtest
new file mode 100644 (file)
index 0000000..ab3b203
--- /dev/null
@@ -0,0 +1,2 @@
+prog: suppfree
+vgopts: --suppressions=suppsrc_sanlineno.supp -q
\ No newline at end of file