Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: chrome/test/kasko/syzyasan_integration_test.py

Issue 2621363002: Remove Kasko! (Closed)
Patch Set: Rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/test/kasko/py/kasko/util.py ('k') | chrome/tools/build/win/FILES.cfg » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/kasko/syzyasan_integration_test.py
diff --git a/chrome/test/kasko/syzyasan_integration_test.py b/chrome/test/kasko/syzyasan_integration_test.py
deleted file mode 100755
index b423cdf62c2d738e3b4c35733b402ebcde17400c..0000000000000000000000000000000000000000
--- a/chrome/test/kasko/syzyasan_integration_test.py
+++ /dev/null
@@ -1,282 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""A Windows-only end-to-end integration test for Kasko and SyzyAsan.
-
-This test ensures that the interface between SyzyAsan, Kasko and Chrome works
-as expected. The test causes a crash that should be detected by SyzyAsan and
-delivered via Kasko to a locally hosted test crash server.
-
-Note that this test only works against non-component Release and Official builds
-of Chrome with Chrome branding, and attempting to use it with anything else will
-most likely lead to constant failures.
-
-Typical usage (assuming in root 'src' directory):
-
-- generate project files with the following GYP variables:
- syzyasan=1 win_z7=0 chromium_win_pch=0
-- build the release Chrome binaries:
- ninja -C out\Release chrome.exe chromedriver.exe
-- run the test:
- python chrome/test/kasko/syzyasan_integration_test.py
-"""
-
-import logging
-import os
-import optparse
-import re
-import shutil
-import subprocess
-import sys
-
-# Bring in the Kasko module.
-KASKO_DIR = os.path.join(os.path.dirname(__file__), 'py')
-sys.path.append(KASKO_DIR)
-import kasko
-
-
-_LOGGER = logging.getLogger(os.path.basename(__file__))
-_CHROME_DLL = 'chrome.dll'
-_INSTRUMENT = 'instrument.exe'
-_SYZYASAN_RTL = 'syzyasan_rtl.dll'
-
-
-def _ParseCommandLine():
- self_dir = os.path.dirname(__file__)
- src_dir = os.path.abspath(os.path.join(self_dir, '..', '..', '..'))
-
- option_parser = kasko.config.GenerateOptionParser()
- option_parser.add_option('--instrumented-dir', dest='instrumented_dir',
- type='string',
- help='Path where instrumented binaries will be placed. If instrumented '
- 'binaries already exist here they will be reused.')
- option_parser.add_option('--skip-instrumentation',
- dest='skip_instrumentation', action='store_true', default=False,
- help='Skips instrumentation if specified. To be used when testing '
- 'against an already instrumented build of Chrome.')
- option_parser.add_option('--syzygy-dir', dest='syzygy_dir', type='string',
- default=os.path.join(src_dir, 'third_party', 'syzygy', 'binaries', 'exe'),
- help='Path to Syzygy binaries. By default will look in third_party.')
- options = kasko.config.ParseCommandLine(option_parser)
-
- if not os.path.isdir(options.syzygy_dir):
- option_parser.error('Invalid syzygy directory.')
- for basename in [_INSTRUMENT, _SYZYASAN_RTL]:
- path = os.path.join(options.syzygy_dir, basename)
- if not os.path.isfile(path):
- option_parser.error('Missing syzygy binary: %s' % path)
-
- _LOGGER.debug('Using syzygy path: %s', options.syzygy_dir)
-
- return options
-
-
-def _DecorateFilename(name, deco):
- """Decorates a filename, transforming 'foo.baz.bar' to 'foo.dec.baz.bar'."""
- d = os.path.dirname(name)
- b = os.path.basename(name)
- b = b.split('.', 1)
- b.insert(1, deco)
- return os.path.join(d, '.'.join(b))
-
-
-def _BackupFile(path, dst_dir):
- """Creates a backup of a file in the specified directory."""
- bak = os.path.abspath(os.path.join(dst_dir, os.path.basename(path)))
- if os.path.exists(bak):
- os.remove(bak)
- # Copy the file, with its permissions and timestamps, etc.
- _LOGGER.debug('Copying "%s" to "%s".' % (path, bak))
- shutil.copyfile(path, bak)
- shutil.copystat(path, bak)
- return bak
-
-
-def _RestoreFile(path, backup):
- """Restores a file from its backup. Leaves the backup file."""
- if not os.path.exists(backup):
- raise Exception('Backup does not exist: %s' % backup)
- if os.path.exists(path):
- os.remove(path)
- _LOGGER.debug('Restoring "%s" from "%s".' % (path, backup))
- shutil.copyfile(backup, path)
- shutil.copystat(backup, path)
-
-
-class _ScopedInstrumentedChrome(object):
- """SyzyAsan Instruments a Chrome installation in-place."""
-
- def __init__(self, chrome_dir, syzygy_dir, temp_dir, instrumented_dir=None,
- verbose=False, skip_instrumentation=False):
- self.chrome_dir_ = chrome_dir
- self.syzygy_dir_ = syzygy_dir
- self.temp_dir_ = temp_dir
- self.instrumented_dir_ = instrumented_dir
- self.verbose_ = verbose
- self.skip_instrumentation_ = skip_instrumentation
-
- def _ProduceInstrumentedBinaries(self):
- # Generate the instrumentation command-line. This will place the
- # instrumented binaries in the temp directory.
- instrument = os.path.abspath(os.path.join(self.syzygy_dir_, _INSTRUMENT))
- cmd = [instrument,
- '--mode=asan',
- '--input-image=%s' % self.chrome_dll_bak_,
- '--input-pdb=%s' % self.chrome_dll_pdb_bak_,
- '--output-image=%s' % self.chrome_dll_inst_,
- '--output-pdb=%s' % self.chrome_dll_pdb_inst_,
- '--no-augment-pdb']
-
- _LOGGER.debug('Instrumenting Chrome binaries.')
-
- # If in verbose mode then let the instrumentation produce output directly.
- if self.verbose_:
- result = subprocess.call(cmd)
- else:
- # Otherwise run the command with all output suppressed.
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- stdout, stderr = proc.communicate()
- result = proc.returncode
- if result != 0:
- sys.stdout.write(stdout)
- sys.stderr.write(stderr)
-
- if result != 0:
- raise Exception('Failed to instrument: %s' % self.chrome_dll_)
-
- return
-
- def __enter__(self):
- """In-place instruments a Chrome installation with SyzyAsan."""
- # Do nothing if instrumentation is to be skipped entirely.
- if self.skip_instrumentation_:
- _LOGGER.debug('Assuming binaries already instrumented.')
- return self
-
- # Build paths to the original Chrome binaries.
- self.chrome_dll_ = os.path.abspath(os.path.join(
- self.chrome_dir_, _CHROME_DLL))
- self.chrome_dll_pdb_ = self.chrome_dll_ + '.pdb'
-
- # Backup the original Chrome binaries to the temp directory.
- orig_dir = os.path.join(self.temp_dir_, 'orig')
- os.makedirs(orig_dir)
- self.chrome_dll_bak_ = _BackupFile(self.chrome_dll_, orig_dir)
- self.chrome_dll_pdb_bak_ = _BackupFile(self.chrome_dll_pdb_, orig_dir)
-
- # Generate the path to the instrumented binaries.
- inst_dir = os.path.join(self.temp_dir_, 'inst')
- if self.instrumented_dir_:
- inst_dir = self.instrumented_dir_
- if not os.path.isdir(inst_dir):
- os.makedirs(inst_dir)
- self.chrome_dll_inst_ = os.path.abspath(os.path.join(
- inst_dir, _DecorateFilename(_CHROME_DLL, 'inst')))
- self.chrome_dll_pdb_inst_ = os.path.abspath(os.path.join(
- inst_dir, _DecorateFilename(_CHROME_DLL + '.pdb', 'inst')))
-
- # Only generate the instrumented binaries if they don't exist.
- if (os.path.isfile(self.chrome_dll_inst_) and
- os.path.isfile(self.chrome_dll_pdb_inst_)):
- _LOGGER.debug('Using existing instrumented binaries.')
- else:
- self._ProduceInstrumentedBinaries()
-
- # Replace the original chrome binaries with the instrumented versions.
- _RestoreFile(self.chrome_dll_, self.chrome_dll_inst_)
- _RestoreFile(self.chrome_dll_pdb_, self.chrome_dll_pdb_inst_)
-
- # Copy the runtime library into the Chrome directory.
- syzyasan_rtl = os.path.abspath(os.path.join(self.syzygy_dir_,
- _SYZYASAN_RTL))
- self.syzyasan_rtl_ = os.path.abspath(os.path.join(self.chrome_dir_,
- _SYZYASAN_RTL))
- _RestoreFile(self.syzyasan_rtl_, syzyasan_rtl)
-
- return self
-
- def __exit__(self, *args, **kwargs):
- # Do nothing if instrumentation is to be skipped entirely.
- if self.skip_instrumentation_:
- return
-
- # Remove the RTL and restore the original Chrome binaries.
- os.remove(self.syzyasan_rtl_)
- _RestoreFile(self.chrome_dll_, self.chrome_dll_bak_)
- _RestoreFile(self.chrome_dll_pdb_, self.chrome_dll_pdb_bak_)
-
-
-def Main():
- options = _ParseCommandLine()
-
- # Generate a temporary directory for use in the tests.
- with kasko.util.ScopedTempDir() as temp_dir:
- try:
- # Prevent the temporary directory from self cleaning if requested.
- if options.keep_temp_dirs:
- temp_dir_path = temp_dir.release()
- else:
- temp_dir_path = temp_dir.path
-
- # Use the specified user data directory if requested.
- if options.user_data_dir:
- user_data_dir = options.user_data_dir
- else:
- user_data_dir = os.path.join(temp_dir_path, 'user-data-dir')
-
- kasko_dir = os.path.join(temp_dir_path, 'kasko')
- os.makedirs(kasko_dir)
-
- # Launch the test server.
- server = kasko.crash_server.CrashServer()
- with kasko.util.ScopedStartStop(server):
- _LOGGER.info('Started server on port %d', server.port)
-
- # Configure the environment so Chrome can find the test crash server.
- os.environ['KASKO_CRASH_SERVER_URL'] = (
- 'http://127.0.0.1:%d/crash' % server.port)
-
- # Configure the environment to disable feature randomization, which can
- # result in Kasko being randomly disabled. Append to any existing
- # options.
- k = 'SYZYGY_ASAN_OPTIONS'
- v = '--disable_feature_randomization'
- if k in os.environ:
- os.environ[k] += ' ' + v
- else:
- os.environ[k] = v
-
- # SyzyAsan instrument the Chrome installation.
- chrome_dir = os.path.dirname(options.chrome)
- with _ScopedInstrumentedChrome(chrome_dir, options.syzygy_dir,
- temp_dir_path, instrumented_dir=options.instrumented_dir,
- verbose=(options.log_level == logging.DEBUG),
- skip_instrumentation=options.skip_instrumentation) as asan_chrome:
- # Launch Chrome and navigate it to the test URL.
- chrome = kasko.process.ChromeInstance(options.chromedriver,
- options.chrome, user_data_dir)
- with kasko.util.ScopedStartStop(chrome):
- _LOGGER.info('Navigating to SyzyAsan debug URL')
- chrome.navigate_to('chrome://crash/browser-use-after-free')
-
- _LOGGER.info('Waiting for Kasko report')
- if not server.wait_for_report(10):
- raise Exception('No Kasko report received.')
-
- report = server.crash(0)
- kasko.report.LogCrashKeys(report)
- kasko.report.ValidateCrashReport(report, {'asan-error-type': 'SyzyAsan'})
-
- _LOGGER.info('Test passed successfully!')
- except Exception as e:
- _LOGGER.error(e)
- return 1
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(Main())
« no previous file with comments | « chrome/test/kasko/py/kasko/util.py ('k') | chrome/tools/build/win/FILES.cfg » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698