build/valgrind/output_handler.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 from __future__ import print_function, unicode_literals
     7 import re
     9 class OutputHandler(object):
    10     '''
    11     A class for handling Valgrind output.
    13     Valgrind errors look like this:
    15     ==60741== 40 (24 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 2,746 of 5,235
    16     ==60741==    at 0x4C26B43: calloc (vg_replace_malloc.c:593)
    17     ==60741==    by 0x63AEF65: PR_Calloc (prmem.c:443)
    18     ==60741==    by 0x69F236E: PORT_ZAlloc_Util (secport.c:117)
    19     ==60741==    by 0x69F1336: SECITEM_AllocItem_Util (secitem.c:28)
    20     ==60741==    by 0xA04280B: ffi_call_unix64 (in /builds/slave/m-in-l64-valgrind-000000000000/objdir/toolkit/library/libxul.so)
    21     ==60741==    by 0xA042443: ffi_call (ffi64.c:485)
    23     For each such error, this class extracts most or all of the first (error
    24     kind) line, plus the function name in each of the first few stack entries.
    25     With this data it constructs and prints a TEST-UNEXPECTED-FAIL message that
    26     TBPL will highlight.
    28     It buffers these lines from which text is extracted so that the
    29     TEST-UNEXPECTED-FAIL message can be printed before the full error.
    31     Parsing the Valgrind output isn't ideal, and it may break in the future if
    32     Valgrind changes the format of the messages, or introduces new error kinds.
    33     To protect against this, we also count how many lines containing
    34     "<insert_a_suppression_name_here>" are seen. Thanks to the use of
    35     --gen-suppressions=yes, exactly one of these lines is present per error. If
    36     the count of these lines doesn't match the error count found during
    37     parsing, then the parsing has missed one or more errors and we can fail
    38     appropriately.
    39     '''
    41     def __init__(self):
    42         # The regexps in this list match all of Valgrind's errors. Note that
    43         # Valgrind is English-only, so we don't have to worry about
    44         # localization.
    45         self.re_error = \
    46             r'==\d+== (' + \
    47             r'(Use of uninitialised value of size \d+)|' + \
    48             r'(Conditional jump or move depends on uninitialised value\(s\))|' + \
    49             r'(Syscall param .* contains uninitialised byte\(s\))|' + \
    50             r'(Syscall param .* points to (unaddressable|uninitialised) byte\(s\))|' + \
    51             r'((Unaddressable|Uninitialised) byte\(s\) found during client check request)|' + \
    52             r'(Invalid free\(\) / delete / delete\[\] / realloc\(\))|' + \
    53             r'(Mismatched free\(\) / delete / delete \[\])|' + \
    54             r'(Invalid (read|write) of size \d+)|' + \
    55             r'(Jump to the invalid address stated on the next line)|' + \
    56             r'(Source and destination overlap in .*)|' + \
    57             r'(.* bytes in .* blocks are .* lost)' + \
    58             r')'
    59         # Match identifer chars, plus ':' for namespaces, and '\?' in order to
    60         # match "???" which Valgrind sometimes produces.
    61         self.re_stack_entry = r'^==\d+==.*0x[A-Z0-9]+: ([A-Za-z0-9_:\?]+)'
    62         self.re_suppression = r' *<insert_a_suppression_name_here>'
    63         self.error_count = 0
    64         self.suppression_count = 0
    65         self.number_of_stack_entries_to_get = 0
    66         self.curr_failure_msg = None
    67         self.buffered_lines = None
    69     def __call__(self, line):
    70         if self.number_of_stack_entries_to_get == 0:
    71             # Look for the start of a Valgrind error.
    72             m = re.search(self.re_error, line)
    73             if m:
    74                 self.error_count += 1
    75                 self.number_of_stack_entries_to_get = 4
    76                 self.curr_failure_msg = 'TEST-UNEXPECTED-FAIL | valgrind-test | ' + m.group(1) + " at "
    77                 self.buffered_lines = [line]
    78             else:
    79                 print(line)
    81         else:
    82             # We've recently found a Valgrind error, and are now extracting
    83             # details from the first few stack entries.
    84             self.buffered_lines.append(line)
    85             m = re.match(self.re_stack_entry, line)
    86             if m:
    87                 self.curr_failure_msg += m.group(1)
    88             else:
    89                 self.curr_failure_msg += '?!?'
    91             self.number_of_stack_entries_to_get -= 1
    92             if self.number_of_stack_entries_to_get != 0:
    93                 self.curr_failure_msg += ' / '
    94             else:
    95                 # We've finished getting the first few stack entries. Print the
    96                 # failure message and the buffered lines, and then reset state.
    97                 print('\n' + self.curr_failure_msg + '\n')
    98                 for b in self.buffered_lines:
    99                     print(b)
   100                 self.curr_failure_msg = None
   101                 self.buffered_lines = None
   103         if re.match(self.re_suppression, line):
   104             self.suppression_count += 1

mercurial