1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7
8from autotest_lib.client.bin import test, utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib.cros import chrome
11from autotest_lib.client.cros import cros_logging
12
13
14class logging_AsanCrash(test.test):
15    """Verify Address Sanitizer does catch memory errors."""
16
17    version = 1
18
19
20    def run_once(self):
21        if not 'asan' in utils.read_file('/etc/ui_use_flags.txt'):
22            raise error.TestFail('Current image not built with ASAN')
23
24        extension_path = os.path.join(os.path.dirname(__file__),
25                                      'asan_crash_ext')
26
27        with chrome.Chrome(extension_paths=[extension_path]) as cr:
28            pid = utils.get_oldest_pid_by_name('chrome')
29            asan_log_name = '/var/log/chrome/asan_log.%d' % pid
30            logging.info('Browser PID under telemetry control is %d. '
31                         'So ASAN log is expected at %s.', pid, asan_log_name)
32
33            logging.info('Initiate simulating memory bug to be caught by ASAN.')
34            extension = cr.get_extension(extension_path)
35            if not extension:
36                raise error.TestFail('Failed to find extension %s'
37                                     % extension_path)
38
39            # Catch the exception raised when the browser crashes.
40            cr.did_browser_crash(lambda: extension.ExecuteJavaScript(
41                    'chrome.autotestPrivate.simulateAsanMemoryBug();'))
42
43            utils.poll_for_condition(
44                    lambda: os.path.isfile(asan_log_name),
45                    timeout=10,
46                    exception=error.TestFail(
47                            'Found no asan log file %s during 10s'
48                            % asan_log_name))
49            ui_log = cros_logging.LogReader(asan_log_name)
50            ui_log.read_all_logs()
51
52            # We must wait some time until memory bug is simulated (happens
53            # immediately after the return on the call) and caught by ASAN.
54            try:
55                utils.poll_for_condition(
56                        lambda: ui_log.can_find('ERROR: AddressSanitizer'),
57                        timeout=10,
58                        exception=error.TestFail(
59                                'Found no asan log message about '
60                                'Address Sanitizer catch'))
61                # An example error string is like this
62                # 'testarray:228' <== Memory access at offset 52 overflows
63                # this variable
64                utils.poll_for_condition(
65                        lambda: ui_log.can_find("'testarray"),
66                        timeout=10,
67                        exception=error.TestFail(
68                                'ASAN caught bug but did not mention '
69                                'the cause in the log'))
70
71            except:
72                logging.debug('ASAN log content: ' + ui_log.get_logs())
73                raise
74
75            # The cbuildbot logic will look for asan logs and process them.
76            # Remove the simulated log file to avoid that.
77            os.remove(asan_log_name)
78