From: Ivo Raisr Date: Mon, 25 Jun 2018 19:52:08 +0000 (+0200) Subject: Ability to add suppressions based on source file name and line number. X-Git-Tag: VALGRIND_3_14_0~92 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=410d736a9928f535e2591c9d5f32e8e0941f96d8;p=thirdparty%2Fvalgrind.git Ability to add suppressions based on source file name and line number. Fixes BZ#390471. Patch based on work by: Jeff Frontz and Joseph M Link. --- diff --git a/NEWS b/NEWS index 0f150563f2..2e13004e41 100644 --- 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 diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c index 38e67699f1..00ffc7ac06 100644 --- a/coregrind/m_errormgr.c +++ b/coregrind/m_errormgr.c @@ -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; } diff --git a/docs/xml/manual-core.xml b/docs/xml/manual-core.xml index 48321acd5b..0e787d75bf 100644 --- a/docs/xml/manual-core.xml +++ b/docs/xml/manual-core.xml @@ -460,13 +460,15 @@ tool_name1,tool_name2:suppression_name]]> the chain of function calls that led to it. There can be up to 24 of these lines. - Locations may be names of either shared objects or - functions. They begin - obj: and - fun: respectively. Function and - object names to match against may use the wildcard characters + Locations may be names of either shared objects, functions, + or source lines. They begin with + obj:, + fun:, or + src: respectively. Function, + object, and file names to match against may use the wildcard characters * and - ?. + ?. Source lines are specified + using the form filename[:lineNumber]. Important note: C++ function names must be mangled. 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. +An example of the src: specification, again for the Memcheck tool: + + + +This suppresses any size-4 uninitialised-value error which occurs +at line 321 in valid.c. + Although the above two examples do not make this clear, you can -freely mix obj: and -fun: lines in a suppression. +freely mix obj:, +fun:, and +src: +lines in a suppression. Finally, here's an example using three frame-level wildcards: diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 38b0822cdf..84e49405f1 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -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 index 0000000000..9ad57cb56d --- /dev/null +++ b/memcheck/tests/suppsrc_lineno.stderr.exp @@ -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 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/suppsrc_lineno.supp b/memcheck/tests/suppsrc_lineno.supp new file mode 100644 index 0000000000..99b6414eee --- /dev/null +++ b/memcheck/tests/suppsrc_lineno.supp @@ -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 index 0000000000..ce6188b464 --- /dev/null +++ b/memcheck/tests/suppsrc_lineno.vgtest @@ -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 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/suppsrc_sanlineno.stdout.exp b/memcheck/tests/suppsrc_sanlineno.stdout.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/suppsrc_sanlineno.supp b/memcheck/tests/suppsrc_sanlineno.supp new file mode 100644 index 0000000000..d92319bcf9 --- /dev/null +++ b/memcheck/tests/suppsrc_sanlineno.supp @@ -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 index 0000000000..ab3b20389d --- /dev/null +++ b/memcheck/tests/suppsrc_sanlineno.vgtest @@ -0,0 +1,2 @@ +prog: suppfree +vgopts: --suppressions=suppsrc_sanlineno.supp -q \ No newline at end of file