15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# suppressions.py
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Post-process Valgrind suppression matcher.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Suppressions are defined as follows:
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# optional one-line comments anywhere in the suppressions file.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  <Short description of the error>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Toolname:Errortype
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fun:function_name
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  obj:object_filename
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fun:wildcarded_fun*_name
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # an ellipsis wildcards zero or more functions in a stack.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ...
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fun:some_other_function_name
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If ran from the command line, suppressions.py does a self-test
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)of the Suppression class.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)sys.path.insert(0, os.path.join(os.path.dirname(__file__),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                '..', 'python', 'google'))
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import path_utils
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ELLIPSIS = '...'
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def GetSuppressions():
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  suppressions_root = path_utils.ScriptDir()
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JOIN = os.path.join
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result = {}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "memcheck", "suppressions.txt")
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vg_common = ReadSuppressionsFromFile(supp_filename)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "tsan", "suppressions.txt")
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tsan_common = ReadSuppressionsFromFile(supp_filename)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['common_suppressions'] = vg_common + tsan_common
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "memcheck", "suppressions_linux.txt")
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vg_linux = ReadSuppressionsFromFile(supp_filename)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "tsan", "suppressions_linux.txt")
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tsan_linux = ReadSuppressionsFromFile(supp_filename)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['linux_suppressions'] = vg_linux + tsan_linux
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "memcheck", "suppressions_mac.txt")
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vg_mac = ReadSuppressionsFromFile(supp_filename)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "tsan", "suppressions_mac.txt")
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tsan_mac = ReadSuppressionsFromFile(supp_filename)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['mac_suppressions'] = vg_mac + tsan_mac
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "tsan", "suppressions_win32.txt")
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tsan_win = ReadSuppressionsFromFile(supp_filename)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['win_suppressions'] = tsan_win
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "drmemory", "suppressions.txt")
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['drmem_suppressions'] = ReadSuppressionsFromFile(supp_filename)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  supp_filename = JOIN(suppressions_root, "drmemory", "suppressions_full.txt")
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result['drmem_full_suppressions'] = ReadSuppressionsFromFile(supp_filename)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GlobToRegex(glob_pattern, ignore_case=False):
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Translate glob wildcards (*?) into regex syntax.  Escape the rest."""
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  regex = ''
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for char in glob_pattern:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if char == '*':
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += '.*'
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif char == '?':
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += '.'
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif ignore_case and char.isalpha():
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += '[%s%s]' % (char.lower(), char.upper())
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += re.escape(char)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ''.join(regex)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def StripAndSkipCommentsIterator(lines):
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Generator of (line_no, line) pairs that strips comments and whitespace."""
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (line_no, line) in enumerate(lines):
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line = line.strip()  # Drop \n
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if line.startswith('#'):
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue  # Comments
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Skip comment lines, but not empty lines, they indicate the end of a
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # suppression.  Add one to the line number as well, since most editors use
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # 1-based numberings, and enumerate is 0-based.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    yield (line_no + 1, line)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Suppression(object):
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """This class represents a single stack trace suppression.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Attributes:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    description: A string representing the error description.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type: A string representing the error type, e.g. Memcheck:Leak.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stack: The lines comprising the stack trace for the suppression.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex: The actual regex used to match against scraped reports.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, description, type, stack, defined_at, regex):
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Inits Suppression.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    description, type, stack, regex: same as class attributes
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined_at: file:line identifying where the suppression was defined
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.description = description
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.type = type
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stack = stack
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.defined_at = defined_at
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.regex = re.compile(regex, re.MULTILINE)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Match(self, suppression_from_report):
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns bool indicating whether this suppression matches
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       the suppression generated from Valgrind error report.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       We match our suppressions against generated suppressions
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (not against reports) since they have the same format
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       while the reports are taken from XML, contain filenames,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       they are demangled, and are generally more difficult to
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       parse.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      suppression_from_report: list of strings (function names).
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      True if the suppression is not empty and matches the report.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not self.stack:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return False
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [f.strip() for f in suppression_from_report]
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.regex.match('\n'.join(lines) + '\n') is not None
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def FilenameToTool(filename):
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Return the name of the tool that a file is related to, or None.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Example mappings:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tools/valgrind/tsan/suppressions.txt -> tsan
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tools/valgrind/drmemory/suppressions.txt -> drmemory
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tools/valgrind/drmemory/suppressions_full.txt -> drmemory
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tools/valgrind/memcheck/suppressions.txt -> memcheck
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tools/valgrind/memcheck/suppressions_mac.txt -> memcheck
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filename = os.path.abspath(filename)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parts = filename.split(os.sep)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tool = parts[-2]
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if tool in ('drmemory', 'memcheck', 'tsan'):
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tool
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return None
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ReadSuppressionsFromFile(filename):
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Read suppressions from the given file and return them as a list"""
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tool_to_parser = {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "drmemory":  ReadDrMemorySuppressions,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "memcheck":  ReadValgrindStyleSuppressions,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tsan":      ReadValgrindStyleSuppressions,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tool = FilenameToTool(filename)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert tool in tool_to_parser, (
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "unknown tool %s for filename %s" % (tool, filename))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parse_func = tool_to_parser[tool]
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  # Consider non-existent files to be empty.
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if not os.path.exists(filename):
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return []
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  input_file = file(filename, 'r')
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try:
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return parse_func(input_file, filename)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  except SuppressionError:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_file.close()
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ValgrindStyleSuppression(Suppression):
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A suppression using the Valgrind syntax.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Most tools, even ones that are not Valgrind-based, use this syntax, ie
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TSan, etc.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Attributes:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Same as Suppression.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, description, type, stack, defined_at):
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    """Creates a suppression using the Memcheck and TSan, syntax."""
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex = '{\n.*\n%s\n' % type
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in stack:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if line == ELLIPSIS:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += '(.*\n)*'
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += GlobToRegex(line)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += '\n'
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex += '(.*\n)*'
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex += '}'
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # In the recent version of valgrind-variant we've switched
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # from memcheck's default Addr[1248]/Value[1248]/Cond suppression types
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # to simply Unaddressable/Uninitialized.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # The suppression generator no longer gives us "old" types thus
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # for the "new-type" suppressions:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #  * Memcheck:Unaddressable should also match Addr* reports,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #  * Memcheck:Uninitialized should also match Cond and Value reports,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We also want to support legacy suppressions (e.g. copied from
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # upstream bugs etc), so:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #  * Memcheck:Addr[1248] suppressions should match Unaddressable reports,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    #  * Memcheck:Cond and Memcheck:Value[1248] should match Uninitialized.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Please note the latest two rules only apply to the
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # tools/valgrind/waterfall.sh suppression matcher and the real
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # valgrind-variant Memcheck will not suppress
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # e.g. Addr1 printed as Unaddressable with Addr4 suppression.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Be careful to check the access size while copying legacy suppressions!
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for sz in [1, 2, 4, 8]:
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex = regex.replace("\nMemcheck:Addr%d\n" % sz,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "\nMemcheck:(Addr%d|Unaddressable)\n" % sz)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex = regex.replace("\nMemcheck:Value%d\n" % sz,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "\nMemcheck:(Value%d|Uninitialized)\n" % sz)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex = regex.replace("\nMemcheck:Cond\n",
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "\nMemcheck:(Cond|Uninitialized)\n")
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex = regex.replace("\nMemcheck:Unaddressable\n",
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "\nMemcheck:(Addr.|Unaddressable)\n")
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex = regex.replace("\nMemcheck:Uninitialized\n",
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          "\nMemcheck:(Cond|Value.|Uninitialized)\n")
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return super(ValgrindStyleSuppression, self).__init__(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        description, type, stack, defined_at, regex)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Stringify."""
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines = [self.description, self.type] + self.stack
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "{\n   %s\n}\n" % "\n   ".join(lines)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SuppressionError(Exception):
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, message, happened_at):
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._message = message
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._happened_at = happened_at
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 'Error reading suppressions at %s!\n%s' % (
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self._happened_at, self._message)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ReadValgrindStyleSuppressions(lines, supp_descriptor):
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Given a list of lines, returns a list of suppressions.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines: a list of lines containing suppressions.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supp_descriptor: should typically be a filename.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Used only when printing errors.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = []
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_descr = ''
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_type = ''
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cur_stack = []
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in_suppression = False
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nline = 0
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for line in lines:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nline += 1
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line = line.strip()
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if line.startswith('#'):
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not in_suppression:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not line:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # empty lines between suppressions
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pass
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif line.startswith('{'):
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        in_suppression = True
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pass
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise SuppressionError('Expected: "{"',
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               "%s:%d" % (supp_descriptor, nline))
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif line.startswith('}'):
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.append(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ValgrindStyleSuppression(cur_descr, cur_type, cur_stack,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "%s:%d" % (supp_descriptor, nline)))
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_descr = ''
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_type = ''
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_stack = []
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_suppression = False
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif not cur_descr:
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_descr = line
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif not cur_type:
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (not line.startswith("Memcheck:") and
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          not line.startswith("ThreadSanitizer:")):
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise SuppressionError(
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            'Expected "Memcheck:TYPE" or "ThreadSanitizer:TYPE", '
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            'got "%s"' % line,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "%s:%d" % (supp_descriptor, nline))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supp_type = line.split(':')[1]
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not supp_type in ["Addr1", "Addr2", "Addr4", "Addr8",
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "Cond", "Free", "Jump", "Leak", "Overlap", "Param",
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "Value1", "Value2", "Value4", "Value8",
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "Race", "UnlockNonLocked", "InvalidLock",
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "Unaddressable", "Uninitialized"]:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        raise SuppressionError('Unknown suppression type "%s"' % supp_type,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               "%s:%d" % (supp_descriptor, nline))
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_type = line
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif re.match("^fun:.*|^obj:.*|^\.\.\.$", line):
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_stack.append(line.strip())
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif len(cur_stack) == 0 and cur_type == "Memcheck:Param":
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cur_stack.append(line.strip())
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise SuppressionError(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '"fun:function_name" or "obj:object_file" or "..." expected',
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "%s:%d" % (supp_descriptor, nline))
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PresubmitCheckSuppressions(supps):
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Check a list of suppressions and return a list of SuppressionErrors.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mostly useful for separating the checking logic from the Presubmit API for
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  known_supp_names = {}  # Key: name, Value: suppression.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors = []
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for s in supps:
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if re.search("<.*suppression.name.here>", s.description):
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Suppression name line is
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # <insert_a_suppression_name_here> for Memcheck,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # <Put your suppression name here> for TSan,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # name=<insert_a_suppression_name_here> for DrMemory
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors.append(
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SuppressionError(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "You've forgotten to put a suppression name like bug_XXX",
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              s.defined_at))
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if s.description in known_supp_names:
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors.append(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SuppressionError(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              'Suppression named "%s" is defined more than once, '
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              'see %s' % (s.description,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          known_supp_names[s.description].defined_at),
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              s.defined_at))
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      known_supp_names[s.description] = s
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return errors
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PresubmitCheck(input_api, output_api):
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A helper function useful in PRESUBMIT.py
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     Returns a list of errors or [].
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sup_regex = re.compile('suppressions.*\.txt$')
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames = [f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   if sup_regex.search(f.LocalPath())]
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors = []
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(timurrrr): warn on putting suppressions into a wrong file,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # e.g. TSan suppression in a memcheck file.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for f in filenames:
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try:
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      supps = ReadSuppressionsFromFile(f)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors.extend(PresubmitCheckSuppressions(supps))
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    except SuppressionError as e:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors.append(e)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return [output_api.PresubmitError(str(e)) for e in errors]
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DrMemorySuppression(Suppression):
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A suppression using the DrMemory syntax.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Attributes:
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instr: The instruction to match.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Rest inherited from Suppression.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, name, report_type, instr, stack, defined_at):
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Constructor."""
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.instr = instr
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Construct the regex.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex = '{\n'
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if report_type == 'LEAK':
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += '(POSSIBLE )?LEAK'
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += report_type
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex += '\nname=.*\n'
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # TODO(rnk): Implement http://crbug.com/107416#c5 .
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # drmemory_analyze.py doesn't generate suppressions with an instruction in
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # them, so these suppressions will always fail to match.  We should override
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Match to fetch the instruction from the report and try to match against
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # that.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if instr:
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      regex += 'instruction=%s\n' % GlobToRegex(instr)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for line in stack:
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if line == ELLIPSIS:
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += '(.*\n)*'
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif '!' in line:
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (mod, func) = line.split('!')
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if func == ELLIPSIS:  # mod!ellipsis frame
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          regex += '(%s\!.*\n)+' % GlobToRegex(mod, ignore_case=True)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:  # mod!func frame
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Ignore case for the module match, but not the function match.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          regex += '%s\!%s\n' % (GlobToRegex(mod, ignore_case=True),
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GlobToRegex(func, ignore_case=False))
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += GlobToRegex(line)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        regex += '\n'
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex += '(.*\n)*'  # Match anything left in the stack.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    regex += '}'
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return super(DrMemorySuppression, self).__init__(name, report_type, stack,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     defined_at, regex)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __str__(self):
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Stringify."""
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    text = self.type + "\n"
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self.description:
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text += "name=%s\n" % self.description
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self.instr:
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text += "instruction=%s\n" % self.instr
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    text += "\n".join(self.stack)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    text += "\n"
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return text
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Possible DrMemory error report types.  Keep consistent with suppress_name
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# array in drmemory/drmemory/report.c.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DRMEMORY_ERROR_TYPES = [
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'UNADDRESSABLE ACCESS',
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'UNINITIALIZED READ',
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'INVALID HEAP ARGUMENT',
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'GDI USAGE ERROR',
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'HANDLE LEAK',
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'LEAK',
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'POSSIBLE LEAK',
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'WARNING',
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Regexes to match valid drmemory frames.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DRMEMORY_FRAME_PATTERNS = [
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^.*\!.*$"),              # mod!func
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^.*!\.\.\.$"),           # mod!ellipsis
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^\<.*\+0x.*\>$"),        # <mod+0xoffs>
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^\<not in a module\>$"),
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^system call .*$"),
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^\*$"),                  # wildcard
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    re.compile(r"^\.\.\.$"),              # ellipsis
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ]
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ReadDrMemorySuppressions(lines, supp_descriptor):
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Given a list of lines, returns a list of DrMemory suppressions.
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lines: a list of lines containing suppressions.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supp_descriptor: should typically be a filename.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Used only when parsing errors happen.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lines = StripAndSkipCommentsIterator(lines)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppressions = []
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (line_no, line) in lines:
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not line:
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if line not in DRMEMORY_ERROR_TYPES:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise SuppressionError('Expected a DrMemory error type, '
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             'found %r instead\n  Valid error types: %s' %
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (line, ' '.join(DRMEMORY_ERROR_TYPES)),
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             "%s:%d" % (supp_descriptor, line_no))
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Suppression starts here.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    report_type = line
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = ''
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instr = None
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stack = []
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined_at = "%s:%d" % (supp_descriptor, line_no)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found_stack = False
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (line_no, line) in lines:
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not found_stack and line.startswith('name='):
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        name = line.replace('name=', '')
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elif not found_stack and line.startswith('instruction='):
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        instr = line.replace('instruction=', '')
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Unrecognized prefix indicates start of stack trace.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        found_stack = True
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not line:
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Blank line means end of suppression.
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not any([regex.match(line) for regex in DRMEMORY_FRAME_PATTERNS]):
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          raise SuppressionError(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ('Unexpected stack frame pattern at line %d\n' +
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               'Frames should be one of the following:\n' +
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' module!function\n' +
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' module!...\n' +
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' <module+0xhexoffset>\n' +
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' <not in a module>\n' +
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' system call Name\n' +
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' *\n' +
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ' ...\n') % line_no, defined_at)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        stack.append(line)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if len(stack) == 0:  # In case we hit EOF or blank without any stack frames.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise SuppressionError('Suppression "%s" has no stack frames, ends at %d'
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             % (name, line_no), defined_at)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if stack[-1] == ELLIPSIS:
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise SuppressionError('Suppression "%s" ends in an ellipsis on line %d' %
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (name, line_no), defined_at)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suppressions.append(
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DrMemorySuppression(name, report_type, instr, stack, defined_at))
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return suppressions
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ParseSuppressionOfType(lines, supp_descriptor, def_line_no, report_type):
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Parse the suppression starting on this line.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Suppressions start with a type, have an optional name and instruction, and a
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack trace that ends in a blank line.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TestStack(stack, positive, negative, suppression_parser=None):
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A helper function for SelfTest() that checks a single stack.
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stack: the stack to match the suppressions.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    positive: the list of suppressions that must match the given stack.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negative: the list of suppressions that should not match.
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suppression_parser: optional arg for the suppression parser, default is
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReadValgrindStyleSuppressions.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not suppression_parser:
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suppression_parser = ReadValgrindStyleSuppressions
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for supp in positive:
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parsed = suppression_parser(supp.split("\n"), "positive_suppression")
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert parsed[0].Match(stack.split("\n")), (
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Suppression:\n%s\ndidn't match stack:\n%s" % (supp, stack))
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for supp in negative:
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parsed = suppression_parser(supp.split("\n"), "negative_suppression")
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert not parsed[0].Match(stack.split("\n")), (
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Suppression:\n%s\ndid match stack:\n%s" % (supp, stack))
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TestFailPresubmit(supp_text, error_text, suppression_parser=None):
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A helper function for SelfTest() that verifies a presubmit check fires.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Args:
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supp_text: suppression text to parse.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_text: text of the presubmit error we expect to find.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suppression_parser: optional arg for the suppression parser, default is
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReadValgrindStyleSuppressions.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not suppression_parser:
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suppression_parser = ReadValgrindStyleSuppressions
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  try:
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    supps = suppression_parser(supp_text.split("\n"), "<presubmit suppression>")
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  except SuppressionError, e:
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If parsing raised an exception, match the error text here.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert error_text in str(e), (
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "presubmit text %r not in SuppressionError:\n%r" %
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (error_text, str(e)))
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Otherwise, run the presubmit checks over the supps.  We expect a single
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # error that has text matching error_text.
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errors = PresubmitCheckSuppressions(supps)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert len(errors) == 1, (
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "expected exactly one presubmit error, got:\n%s" % errors)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert error_text in str(errors[0]), (
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "presubmit text %r not in SuppressionError:\n%r" %
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (error_text, str(errors[0])))
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def SelfTest():
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Tests the Suppression.Match() capabilities."""
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_memcheck_stack_1 = """{
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Memcheck:Leak
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:absolutly
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:brilliant
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj:condition
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:detection
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:expression
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_memcheck_stack_2 = """{
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Memcheck:Uninitialized
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:absolutly
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:brilliant
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj:condition
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:detection
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:expression
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_memcheck_stack_3 = """{
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Memcheck:Unaddressable
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:absolutly
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:brilliant
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj:condition
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:detection
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:expression
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_memcheck_stack_4 = """{
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Memcheck:Addr4
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:absolutly
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:brilliant
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj:condition
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:detection
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:expression
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_tsan_stack = """{
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ThreadSanitizer:Race
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:absolutly
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:brilliant
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    obj:condition
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:detection
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:expression
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_memcheck_suppressions_1 = [
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:absolutly\n}",
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:ab*ly\n}",
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:absolutly\nfun:brilliant\n}",
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\n...\nfun:brilliant\n}",
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\n...\nfun:detection\n}",
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:absolutly\n...\nfun:detection\n}",
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:ab*ly\n...\nfun:detection\n}",
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\n...\nobj:condition\n}",
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\n...\nobj:condition\nfun:detection\n}",
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\n...\nfun:brilliant\nobj:condition\n}",
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_memcheck_suppressions_2 = [
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\n}",
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Uninitialized\nfun:ab*ly\n}",
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\nfun:brilliant\n}",
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Legacy suppression types
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value1\n...\nfun:brilliant\n}",
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Cond\n...\nfun:detection\n}",
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value8\nfun:absolutly\nfun:brilliant\n}",
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_memcheck_suppressions_3 = [
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\n}",
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\nfun:brilliant\n}",
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\nfun:brilliant\n}",
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Legacy suppression types
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr1\n...\nfun:brilliant\n}",
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr8\n...\nfun:detection\n}",
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_memcheck_suppressions_4 = [
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr4\nfun:absolutly\n}",
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\n}",
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr4\nfun:absolutly\nfun:brilliant\n}",
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\n...\nfun:brilliant\n}",
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr4\n...\nfun:detection\n}",
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_tsan_suppressions = [
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nThreadSanitizer:Race\n...\nobj:condition\n}",
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nThreadSanitizer:Race\nfun:absolutly\n}",
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_memcheck_suppressions_1 = [
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:abnormal\n}",
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:ab*liant\n}",
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nfun:brilliant\n}",
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_memcheck_suppressions_2 = [
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Cond\nfun:abnormal\n}",
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value2\nfun:abnormal\n}",
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Uninitialized\nfun:ab*liant\n}",
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:brilliant\n}",
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_memcheck_suppressions_3 = [
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr1\nfun:abnormal\n}",
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\n}",
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr2\nfun:ab*liant\n}",
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_memcheck_suppressions_4 = [
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr1\nfun:abnormal\n}",
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr4\nfun:abnormal\n}",
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Unaddressable\nfun:abnormal\n}",
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr1\nfun:absolutly\n}",
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr2\nfun:ab*liant\n}",
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_tsan_suppressions = [
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nThreadSanitizer:Leak\nfun:absolutly\n}",
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "{\nzzz\nThreadSanitizer:Race\nfun:brilliant\n}",
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(test_memcheck_stack_1,
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            positive_memcheck_suppressions_1,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            negative_memcheck_suppressions_1)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(test_memcheck_stack_2,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            positive_memcheck_suppressions_2,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            negative_memcheck_suppressions_2)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(test_memcheck_stack_3,
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            positive_memcheck_suppressions_3,
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            negative_memcheck_suppressions_3)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(test_memcheck_stack_4,
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            positive_memcheck_suppressions_4,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            negative_memcheck_suppressions_4)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(test_tsan_stack, positive_tsan_suppressions,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            negative_tsan_suppressions)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # TODO(timurrrr): add TestFailPresubmit tests.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ### DrMemory self tests.
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # http://crbug.com/96010 suppression.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_96010 = """{
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert_a_suppression_name_here>
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!TestingProfile::FinishInit
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!TestingProfile::TestingProfile
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!testing::Test::Run
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_96010 = [
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\nname=zzz\n...\n*!testing::Test::Run\n",
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ("UNADDRESSABLE ACCESS\nname=zzz\n...\n" +
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "*!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody\n"),
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\nname=zzz\n...\n*!BrowserAboutHandlerTest*\n",
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\nname=zzz\n*!TestingProfile::FinishInit\n",
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # No name should be needed
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\n*!TestingProfile::FinishInit\n",
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Whole trace
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ("UNADDRESSABLE ACCESS\n" +
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "*!TestingProfile::FinishInit\n" +
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "*!TestingProfile::TestingProfile\n" +
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "*!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody\n" +
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "*!testing::Test::Run\n"),
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_96010 = [
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Wrong type
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNINITIALIZED READ\nname=zzz\n*!TestingProfile::FinishInit\n",
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # No ellipsis
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\nname=zzz\n*!BrowserAboutHandlerTest*\n",
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_96010, suppress_96010, negative_96010,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Invalid heap arg
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_invalid = """{
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INVALID HEAP ARGUMENT
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=asdf
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!foo
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_invalid = [
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "INVALID HEAP ARGUMENT\n*!foo\n",
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_invalid = [
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\n*!foo\n",
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_invalid, suppress_invalid, negative_invalid,
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Suppress only ntdll
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_in_ntdll = """{
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert_a_suppression_name_here>
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntdll.dll!RtlTryEnterCriticalSection
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_not_ntdll = """{
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert_a_suppression_name_here>
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notntdll.dll!RtlTryEnterCriticalSection
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_in_ntdll = [
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\nntdll.dll!RtlTryEnterCriticalSection\n",
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_in_any = [
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "UNADDRESSABLE ACCESS\n*!RtlTryEnterCriticalSection\n",
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ]
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_in_ntdll, suppress_in_ntdll + suppress_in_any, [],
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Make sure we don't wildcard away the "not" part and match ntdll.dll by
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # accident.
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_not_ntdll, suppress_in_any, suppress_in_ntdll,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Suppress a POSSIBLE LEAK with LEAK.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_foo_possible = """{
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    POSSIBLE LEAK
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=foo possible
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!foo
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_foo_possible = [ "POSSIBLE LEAK\n*!foo\n" ]
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_foo_leak = [ "LEAK\n*!foo\n" ]
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_foo_possible, suppress_foo_possible + suppress_foo_leak, [],
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Don't suppress LEAK with POSSIBLE LEAK.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_foo_leak = """{
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LEAK
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=foo leak
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!foo
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_foo_leak, suppress_foo_leak, suppress_foo_possible,
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test case insensitivity of module names.
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_user32_mixed_case = """{
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LEAK
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert>
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    USER32.dll!foo
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user32.DLL!bar
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user32.dll!baz
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_user32 = [  # Module name case doesn't matter.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nuser32.dll!foo\nuser32.dll!bar\nuser32.dll!baz\n",
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nUSER32.DLL!foo\nUSER32.DLL!bar\nUSER32.DLL!baz\n",
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ]
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  no_suppress_user32 = [  # Function name case matters.
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nuser32.dll!FOO\nuser32.dll!BAR\nuser32.dll!BAZ\n",
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nUSER32.DLL!FOO\nUSER32.DLL!BAR\nUSER32.DLL!BAZ\n",
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ]
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_user32_mixed_case, suppress_user32, no_suppress_user32,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test mod!... frames.
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stack_kernel32_through_ntdll = """{
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LEAK
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert>
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kernel32.dll!foo
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    KERNEL32.dll!bar
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kernel32.DLL!baz
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntdll.dll!quux
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }"""
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  suppress_mod_ellipsis = [
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nkernel32.dll!...\nntdll.dll!quux\n",
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nKERNEL32.DLL!...\nntdll.dll!quux\n",
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ]
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  no_suppress_mod_ellipsis = [
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Need one or more matching frames, not zero, unlike regular ellipsis.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "LEAK\nuser32.dll!...\nkernel32.dll!...\nntdll.dll!quux\n",
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ]
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestStack(stack_kernel32_through_ntdll, suppress_mod_ellipsis,
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            no_suppress_mod_ellipsis,
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            suppression_parser=ReadDrMemorySuppressions)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test that the presubmit checks work.
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  forgot_to_name = """
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=<insert_a_suppression_name_here>
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntdll.dll!RtlTryEnterCriticalSection
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailPresubmit(forgot_to_name, 'forgotten to put a suppression',
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    suppression_parser=ReadDrMemorySuppressions)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  named_twice = """
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=http://crbug.com/1234
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!foo
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=http://crbug.com/1234
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *!bar
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailPresubmit(named_twice, 'defined more than once',
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    suppression_parser=ReadDrMemorySuppressions)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  forgot_stack = """
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=http://crbug.com/1234
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailPresubmit(forgot_stack, 'has no stack frames',
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    suppression_parser=ReadDrMemorySuppressions)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ends_in_ellipsis = """
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=http://crbug.com/1234
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ntdll.dll!RtlTryEnterCriticalSection
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ...
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailPresubmit(ends_in_ellipsis, 'ends in an ellipsis',
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    suppression_parser=ReadDrMemorySuppressions)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bad_stack_frame = """
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNADDRESSABLE ACCESS
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name=http://crbug.com/1234
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fun:memcheck_style_frame
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFailPresubmit(bad_stack_frame, 'Unexpected stack frame pattern',
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    suppression_parser=ReadDrMemorySuppressions)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test FilenameToTool.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames_to_tools = {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/tsan/suppressions.txt": "tsan",
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/drmemory/suppressions.txt": "drmemory",
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/drmemory/suppressions_full.txt": "drmemory",
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/memcheck/suppressions.txt": "memcheck",
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "asdf/tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "foo/bar/baz/tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "foo/bar/baz/tools/valgrind/suppressions.txt": None,
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "tools/valgrind/suppressions.txt": None,
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (filename, expected_tool) in filenames_to_tools.items():
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filename.replace('/', os.sep)  # Make the path look native.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tool = FilenameToTool(filename)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert tool == expected_tool, (
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "failed to get expected tool for filename %r, expected %s, got %s" %
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (filename, expected_tool, tool))
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test ValgrindStyleSuppression.__str__.
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp = ValgrindStyleSuppression("http://crbug.com/1234", "Memcheck:Leak",
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ["...", "fun:foo"], "supp.txt:1")
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Intentional 3-space indent.  =/
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp_str = ("{\n"
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "   http://crbug.com/1234\n"
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "   Memcheck:Leak\n"
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "   ...\n"
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "   fun:foo\n"
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "}\n")
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert str(supp) == supp_str, (
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Test DrMemorySuppression.__str__.
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp = DrMemorySuppression(
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://crbug.com/1234", "LEAK", None, ["...", "*!foo"], "supp.txt:1")
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp_str = ("LEAK\n"
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "name=http://crbug.com/1234\n"
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "...\n"
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "*!foo\n")
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert str(supp) == supp_str, (
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp = DrMemorySuppression(
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "http://crbug.com/1234", "UNINITIALIZED READ", "test 0x08(%eax) $0x01",
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ["ntdll.dll!*", "*!foo"], "supp.txt:1")
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  supp_str = ("UNINITIALIZED READ\n"
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "name=http://crbug.com/1234\n"
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "instruction=test 0x08(%eax) $0x01\n"
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "ntdll.dll!*\n"
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "*!foo\n")
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert str(supp) == supp_str, (
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelfTest()
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print 'PASS'
990