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

Unified Diff: tools/isolate/run_test_from_archive.py

Issue 10880009: Enforces strict manifest content. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Implemented lower-overhead straight forward technique Created 8 years, 4 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 | « no previous file | tools/isolate/run_test_from_archive_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/isolate/run_test_from_archive.py
diff --git a/tools/isolate/run_test_from_archive.py b/tools/isolate/run_test_from_archive.py
index d8b2bed74fb6859da0ef3f4f7b7860de424ac2fa..e568899929437d72efe520175db308ea379b713a 100755
--- a/tools/isolate/run_test_from_archive.py
+++ b/tools/isolate/run_test_from_archive.py
@@ -26,6 +26,13 @@ import urllib
# Types of action accepted by recreate_tree().
HARDLINK, SYMLINK, COPY = range(1, 4)
+RE_IS_SHA1 = re.compile(r'^[a-fA-F0-9]{40}$')
+
+
+class ConfigError(ValueError):
+ """Generic failure to load a manifest."""
+ pass
+
class MappingError(OSError):
"""Failed to recreate the tree."""
@@ -172,6 +179,62 @@ def make_temp_dir(prefix, root_dir):
return tempfile.mkdtemp(prefix=prefix, dir=base_temp_dir)
+def load_manifest(content):
+ """Verifies the manifest is valid and loads this object with the json data.
+ """
+ data = json.loads(content)
+ if not isinstance(data, dict):
+ raise ConfigError('Expected dict, got %r' % data)
+
+ for key, value in data.iteritems():
+ if key == 'command':
+ if not isinstance(value, list):
+ raise ConfigError('Expected list, got %r' % value)
+ for subvalue in value:
+ if not isinstance(subvalue, basestring):
+ raise ConfigError('Expected string, got %r' % subvalue)
+
+ elif key == 'files':
+ if not isinstance(value, dict):
+ raise ConfigError('Expected dict, got %r' % value)
+ for subkey, subvalue in value.iteritems():
+ if not isinstance(subkey, basestring):
+ raise ConfigError('Expected string, got %r' % subkey)
+ if not isinstance(subvalue, dict):
+ raise ConfigError('Expected dict, got %r' % subvalue)
+ for subsubkey, subsubvalue in subvalue.iteritems():
M-A Ruel 2012/08/28 20:51:02 The main issue is that it's much easier to make a
+ if subsubkey == 'link':
+ if not isinstance(subsubvalue, basestring):
+ raise ConfigError('Expected string, got %r' % subsubvalue)
+ elif subsubkey == 'mode':
+ if not isinstance(subsubvalue, int):
+ raise ConfigError('Expected int, got %r' % subsubvalue)
+ elif subsubkey == 'sha-1':
+ if not RE_IS_SHA1.match(subsubvalue):
+ raise ConfigError('Expected sha-1, got %r' % subsubvalue)
+ elif subsubkey == 'timestamp':
+ if not isinstance(subsubvalue, int):
+ raise ConfigError('Expected int, got %r' % subsubvalue)
+ else:
+ raise ConfigError('Unknown key %s' % subsubkey)
+ if bool('sha-1' in subvalue) and bool('link' in subvalue):
+ raise ConfigError(
+ 'Did not expect both \'sha-1\' and \'link\', got: %r' % subvalue)
+
+ elif key == 'read_only':
+ if not isinstance(value, bool):
+ raise ConfigError('Expected bool, got %r' % value)
+
+ elif key == 'relative_cwd':
+ if not isinstance(value, basestring):
+ raise ConfigError('Expected string, got %r' % value)
+
+ else:
+ raise ConfigError('Unknown key %s' % subkey)
+
+ return data
+
+
def fix_python_path(cmd):
"""Returns the fixed command line to call the right python executable."""
out = cmd[:]
@@ -394,7 +457,7 @@ def run_tha_test(manifest, cache_dir, remote, policies):
# A symlink.
os.symlink(properties['link'], outfile)
else:
- raise ValueError('Unexpected entry: %s' % properties)
+ raise ConfigError('Unexpected entry: %s' % properties)
if 'mode' in properties:
# It's not set on Windows.
os.chmod(outfile, properties['mode'])
@@ -483,7 +546,7 @@ def main():
# First calculate the reference to it.
options.manifest = '%s/%s' % (options.remote.rstrip('/'), options.hash)
try:
- manifest = json.load(open_remote(options.manifest))
+ manifest = load_manifest(open_remote(options.manifest).read())
except IOError as e:
parser.error(
'Failed to read manifest %s; remote:%s; hash:%s; %s' %
@@ -497,7 +560,7 @@ def main():
os.path.abspath(options.cache),
options.remote,
policies)
- except MappingError, e:
+ except (ConfigError, MappingError), e:
print >> sys.stderr, str(e)
return 1
« no previous file with comments | « no previous file | tools/isolate/run_test_from_archive_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698