OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """The frontend for the Mojo bindings system.""" | 6 """The frontend for the Mojo bindings system.""" |
7 | 7 |
8 | 8 |
9 import argparse | 9 import argparse |
| 10 import hashlib |
10 import imp | 11 import imp |
11 import json | 12 import json |
12 import os | 13 import os |
13 import pprint | 14 import pprint |
14 import re | 15 import re |
| 16 import struct |
15 import sys | 17 import sys |
16 | 18 |
17 # Disable lint check for finding modules: | 19 # Disable lint check for finding modules: |
18 # pylint: disable=F0401 | 20 # pylint: disable=F0401 |
19 | 21 |
20 def _GetDirAbove(dirname): | 22 def _GetDirAbove(dirname): |
21 """Returns the directory "above" this file containing |dirname| (which must | 23 """Returns the directory "above" this file containing |dirname| (which must |
22 also be "above" this file).""" | 24 also be "above" this file).""" |
23 path = os.path.abspath(__file__) | 25 path = os.path.abspath(__file__) |
24 while True: | 26 while True: |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 RelativePath with first file found, or an arbitrary non-existent file | 95 RelativePath with first file found, or an arbitrary non-existent file |
94 otherwise.""" | 96 otherwise.""" |
95 for rel_search_dir in [rel_dir] + search_rel_dirs: | 97 for rel_search_dir in [rel_dir] + search_rel_dirs: |
96 path = os.path.join(rel_search_dir.path, file_name) | 98 path = os.path.join(rel_search_dir.path, file_name) |
97 if os.path.isfile(path): | 99 if os.path.isfile(path): |
98 return RelativePath(path, rel_search_dir.source_root) | 100 return RelativePath(path, rel_search_dir.source_root) |
99 return RelativePath(os.path.join(rel_dir.path, file_name), | 101 return RelativePath(os.path.join(rel_dir.path, file_name), |
100 rel_dir.source_root) | 102 rel_dir.source_root) |
101 | 103 |
102 | 104 |
| 105 def ScrambleMethodOrdinals(interfaces, salt): |
| 106 already_generated = set() |
| 107 for interface in interfaces: |
| 108 i = 0 |
| 109 already_generated.clear() |
| 110 for method in interface.methods: |
| 111 while True: |
| 112 i = i + 1 |
| 113 if i == 1000000: |
| 114 raise Exception("Could not generate %d method ordinals for %s" % |
| 115 (len(interface.methods), interface.name)) |
| 116 # Generate a scrambled method.ordinal value. The algorithm doesn't have |
| 117 # to be very strong, cryptographically. It just needs to be non-trivial |
| 118 # to guess the results without the secret salt, in order to make it |
| 119 # harder for a compromised process to send fake Mojo messages. |
| 120 sha256 = hashlib.sha256(salt) |
| 121 sha256.update(interface.name) |
| 122 sha256.update(str(i)) |
| 123 # Take the first 4 bytes as a little-endian uint32. |
| 124 ordinal = struct.unpack('<L', sha256.digest()[:4])[0] |
| 125 # Trim to 31 bits, so it always fits into a Java (signed) int. |
| 126 ordinal = ordinal & 0x7fffffff |
| 127 if ordinal in already_generated: |
| 128 continue |
| 129 already_generated.add(ordinal) |
| 130 method.ordinal = ordinal |
| 131 method.ordinal_comment = ( |
| 132 'The %s value is based on sha256(salt + "%s%d").' % |
| 133 (ordinal, interface.name, i)) |
| 134 break |
| 135 |
| 136 |
103 class MojomProcessor(object): | 137 class MojomProcessor(object): |
104 """Parses mojom files and creates ASTs for them. | 138 """Parses mojom files and creates ASTs for them. |
105 | 139 |
106 Attributes: | 140 Attributes: |
107 _processed_files: {Dict[str, mojom.generate.module.Module]} Mapping from | 141 _processed_files: {Dict[str, mojom.generate.module.Module]} Mapping from |
108 relative mojom filename paths to the module AST for that mojom file. | 142 relative mojom filename paths to the module AST for that mojom file. |
109 """ | 143 """ |
110 def __init__(self, should_generate): | 144 def __init__(self, should_generate): |
111 self._should_generate = should_generate | 145 self._should_generate = should_generate |
112 self._processed_files = {} | 146 self._processed_files = {} |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 imports = {} | 181 imports = {} |
148 for parsed_imp in tree.import_list: | 182 for parsed_imp in tree.import_list: |
149 rel_import_file = FindImportFile( | 183 rel_import_file = FindImportFile( |
150 RelativePath(dirname, rel_filename.source_root), | 184 RelativePath(dirname, rel_filename.source_root), |
151 parsed_imp.import_filename, args.import_directories) | 185 parsed_imp.import_filename, args.import_directories) |
152 imports[parsed_imp.import_filename] = self._GenerateModule( | 186 imports[parsed_imp.import_filename] = self._GenerateModule( |
153 args, remaining_args, generator_modules, rel_import_file) | 187 args, remaining_args, generator_modules, rel_import_file) |
154 | 188 |
155 module = translate.OrderedModule(tree, name, imports) | 189 module = translate.OrderedModule(tree, name, imports) |
156 | 190 |
| 191 if args.scrambled_message_id_salt: |
| 192 ScrambleMethodOrdinals(module.interfaces, args.scrambled_message_id_salt) |
| 193 |
157 # Set the path as relative to the source root. | 194 # Set the path as relative to the source root. |
158 module.path = rel_filename.relative_path() | 195 module.path = rel_filename.relative_path() |
159 | 196 |
160 # Normalize to unix-style path here to keep the generators simpler. | 197 # Normalize to unix-style path here to keep the generators simpler. |
161 module.path = module.path.replace('\\', '/') | 198 module.path = module.path.replace('\\', '/') |
162 | 199 |
163 if self._should_generate(rel_filename.path): | 200 if self._should_generate(rel_filename.path): |
164 for language, generator_module in generator_modules.iteritems(): | 201 for language, generator_module in generator_modules.iteritems(): |
165 generator = generator_module.Generator( | 202 generator = generator_module.Generator( |
166 module, args.output_dir, typemap=self._typemap.get(language, {}), | 203 module, args.output_dir, typemap=self._typemap.get(language, {}), |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 "component build.") | 349 "component build.") |
313 generate_parser.add_argument( | 350 generate_parser.add_argument( |
314 "--generate_non_variant_code", action="store_true", | 351 "--generate_non_variant_code", action="store_true", |
315 help="Generate code that is shared by different variants.") | 352 help="Generate code that is shared by different variants.") |
316 generate_parser.add_argument( | 353 generate_parser.add_argument( |
317 "--depfile", type=str, | 354 "--depfile", type=str, |
318 help="A file into which the list of input files will be written.") | 355 help="A file into which the list of input files will be written.") |
319 generate_parser.add_argument( | 356 generate_parser.add_argument( |
320 "--depfile_target", type=str, | 357 "--depfile_target", type=str, |
321 help="The target name to use in the depfile.") | 358 help="The target name to use in the depfile.") |
| 359 generate_parser.add_argument( |
| 360 "--scrambled_message_id_salt", |
| 361 help="If non-empty, the salt for generating scrambled message IDs.") |
322 generate_parser.set_defaults(func=_Generate) | 362 generate_parser.set_defaults(func=_Generate) |
323 | 363 |
324 precompile_parser = subparsers.add_parser("precompile", | 364 precompile_parser = subparsers.add_parser("precompile", |
325 description="Precompile templates for the mojom bindings generator.") | 365 description="Precompile templates for the mojom bindings generator.") |
326 precompile_parser.add_argument( | 366 precompile_parser.add_argument( |
327 "-o", "--output_dir", dest="output_dir", default=".", | 367 "-o", "--output_dir", dest="output_dir", default=".", |
328 help="output directory for precompiled templates") | 368 help="output directory for precompiled templates") |
329 precompile_parser.set_defaults(func=_Precompile) | 369 precompile_parser.set_defaults(func=_Precompile) |
330 | 370 |
331 args, remaining_args = parser.parse_known_args() | 371 args, remaining_args = parser.parse_known_args() |
332 return args.func(args, remaining_args) | 372 return args.func(args, remaining_args) |
333 | 373 |
334 | 374 |
335 if __name__ == "__main__": | 375 if __name__ == "__main__": |
336 sys.exit(main()) | 376 sys.exit(main()) |
OLD | NEW |