From 578037dedf557806a5a39ab40a22b9cceade9a07 Mon Sep 17 00:00:00 2001 From: The6P4C Date: Sun, 8 Dec 2019 23:27:46 +1000 Subject: icepack: Fix Windows-only stack overflow in CRAM pbm generation (fixes #241) On Windows, attempting to generate a netpbm image of the CRAM with `icepack -b` causes the tool to crash after writing only the netpbm header due to a stack overflow. The bug did not appear on Linux. This was traced to a large stack-allocated variable length array (`tile_type`) inside `FpgaConfig::write_cram_pbm`. For an 8k ice40 with 4 banks, `cram_width = 872` and `cram_height = 272` the `tile_type` array ends up at `4 * 872 * 272 * sizeof(uint32_t) =` 3794944 bytes, or about 3.6 MiB. The fix replaces the large stack VLA with an array of 4 (bank) 2D C++ vectors, moving the large amount of data to the heap. Even though the fix is not in a Windows-specific code path (and hence applies to all platforms), I think it's wise to eliminate such a large stack allocation entirely. The fix has been tested working on both Windows and an Ubuntu WSL install. --- icepack/icepack.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'icepack') diff --git a/icepack/icepack.cc b/icepack/icepack.cc index 9b38ab5..2eec7ed 100644 --- a/icepack/icepack.cc +++ b/icepack/icepack.cc @@ -968,7 +968,25 @@ void FpgaConfig::write_cram_pbm(std::ostream &ofs, int bank_num) const ofs << "P3\n"; ofs << stringf("%d %d\n", 2*this->cram_width, 2*this->cram_height); ofs << "255\n"; - uint32_t tile_type[4][this->cram_width][this->cram_height]; + + vector> tile_type[4]; + + // We require random access to tile_type, so ensure that each column of each + // bank is initialised so that all possible indices are valid + for (int bank = 0; bank < 4; bank++) { + tile_type[bank].reserve(this->cram_width); + + for (int x = 0; x < this->cram_width; x++) { + tile_type[bank].push_back(vector(this->cram_height)); + + for (int y = 0; y < this->cram_height; y++) { + // Initialisation value unimportant - will be overwritten during + // image generation + tile_type[bank][x].push_back(0); + } + } + } + for (int y = 0; y <= this->chip_height()+1; y++) for (int x = 0; x <= this->chip_width()+1; x++) { -- cgit v1.2.3