From 4393e4b82a42a4c21829a057e563e11f1f1d2a39 Mon Sep 17 00:00:00 2001 From: Naveen Kaje Date: Mon, 7 Jan 2019 14:29:37 -0600 Subject: [PATCH 1/2] tools: check part size is not exceeding region size If config is specified, check that part size is not exceeding the region. Normally we now assume that part.maxaddr() can be beyond end of rom. --- tools/build_api.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/build_api.py b/tools/build_api.py index 54c39e59d7..b8b3c19eae 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -411,7 +411,7 @@ def _fill_header(region_list, current_region): return header -def merge_region_list(region_list, destination, notify, padding=b'\xFF'): +def merge_region_list(region_list, destination, notify, config, padding=b'\xFF'): """Merge the region_list into a single image Positional Arguments: @@ -435,6 +435,13 @@ def merge_region_list(region_list, destination, notify, padding=b'\xFF'): notify.info(" Filling region %s with %s" % (region.name, region.filename)) part = intelhex_offset(region.filename, offset=region.start) part.start_addr = None + # Normally, we assume that part.maxddr() can be beyond + # end of rom. However, if the size is restricted with config, do check. + if config.target.restrict_size is not None: + part_size = (part.maxaddr() - part.minaddr()) + 1 + if part_size > region.size: + raise ToolException("Contents of region %s does not fit" + % region.name) merged.merge(part) # Hex file can have gaps, so no padding needed. While other formats may @@ -555,13 +562,13 @@ def build_project(src_paths, build_path, target, toolchain_name, for r in region_list] res = "%s.%s" % (join(build_path, name), getattr(toolchain.target, "OUTPUT_EXT", "bin")) - merge_region_list(region_list, res, notify) + merge_region_list(region_list, res, notify, toolchain.config) update_regions = [ r for r in region_list if r.name in UPDATE_WHITELIST ] if update_regions: update_res = join(build_path, generate_update_filename(name, toolchain.target)) - merge_region_list(update_regions, update_res, notify) + merge_region_list(update_regions, update_res, notify, toolchain.config) res = (res, update_res) else: res = (res, None) From 43da2f22af5e63292a177636739f2767fee9d234 Mon Sep 17 00:00:00 2001 From: Naveen Kaje Date: Tue, 29 Jan 2019 09:11:09 -0600 Subject: [PATCH 2/2] tools: build_api_test: add test to detect when part overflows region size --- tools/test/build_api/build_api_test.py | 38 ++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/tools/test/build_api/build_api_test.py b/tools/test/build_api/build_api_test.py index 2fcfc947b8..cc397df839 100644 --- a/tools/test/build_api/build_api_test.py +++ b/tools/test/build_api/build_api_test.py @@ -18,11 +18,14 @@ limitations under the License. import unittest from collections import namedtuple from mock import patch, MagicMock -from tools.build_api import prepare_toolchain, build_project, build_library +from tools.build_api import prepare_toolchain, build_project, build_library, merge_region_list from tools.resources import Resources from tools.toolchains import TOOLCHAINS from tools.notifier.mock import MockNotifier - +from tools.config import Region +from tools.utils import ToolException +from intelhex import IntelHex +import intelhex """ Tests for build_api.py """ @@ -240,5 +243,36 @@ class BuildApiTests(unittest.TestCase): self.assertEqual(args[1]['app_config'], None, "prepare_toolchain was called with an incorrect app_config") + @patch('tools.build_api.intelhex_offset') + @patch('tools.config') + def test_merge_region_no_fit(self, mock_config, mock_intelhex_offset): + """ + Test that merge region fails as expected when part size overflows region size. + """ + max_addr = 87444 + # create a dummy hex file with above max_addr + mock_intelhex_offset.return_value = IntelHex({0:2, max_addr:0}) + + # create application and post-application regions and merge. + region_application = Region("application", 10000, 86000, True, "random.hex") + region_post_application = Region("postapplication", 100000, 90000, False, None) + + notify = MockNotifier() + region_list = [region_application, region_post_application] + # path to store the result in, should not get used as we expect exception. + res = "./" + mock_config.target.restrict_size = 90000 + toolexception = False + + try: + merge_region_list(region_list, res, notify, mock_config) + except ToolException: + toolexception = True + except Exception as e: + print("%s %s" % (e.message, e.args)) + + self.assertTrue(toolexception, "Expected ToolException not raised") + + if __name__ == '__main__': unittest.main()