Skip to content

Commit 8e64d1e

Browse files
Merge pull request #2321 from KLayout/bugfix/issue-2320
Fixing issue #2320
2 parents 3fae0aa + 615658c commit 8e64d1e

3 files changed

Lines changed: 97 additions & 12 deletions

File tree

src/plugins/streamers/oasis/unit_tests/dbOASISReaderTests.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "dbOASISWriter.h"
2626
#include "dbTextWriter.h"
2727
#include "dbTestSupport.h"
28+
#include "dbLayoutDiff.h"
2829
#include "tlLog.h"
2930
#include "tlUnitTest.h"
3031
#include "tlStream.h"
@@ -696,3 +697,49 @@ TEST(BlendCrash)
696697
std::string fn_au (tl::testdata () + "/oasis/blend_crash_au.gds.gz");
697698
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
698699
}
700+
701+
TEST(CBlockLargePropertyString)
702+
{
703+
// NOTE: we try different blob sizes for triggering various reallocation szenarios
704+
for (size_t f = 0; f < 50; ++f) {
705+
706+
size_t blob_size = size_t (12345) * f;
707+
708+
tl::info << "Trying blob size of " << blob_size;
709+
710+
db::Layout layout_org (false);
711+
712+
unsigned int layer = layout_org.insert_layer (db::LayerProperties (1, 0));
713+
db::Cell &top = layout_org.cell (layout_org.add_cell ("TOP"));
714+
715+
std::string large_value (blob_size, 'a');
716+
717+
db::PropertiesSet ps;
718+
ps.insert (db::property_names_id (tl::Variant ("blob")), tl::Variant (large_value));
719+
720+
top.shapes (layer).insert (db::BoxWithProperties (db::Box (0, 0, 100, 100), db::properties_id (ps)));
721+
722+
std::string tmp_file = tl::TestBase::tmp_file ("tmp_OASISReaderLargeString.oas");
723+
724+
{
725+
tl::OutputStream out (tmp_file);
726+
db::SaveLayoutOptions options;
727+
db::OASISWriterOptions &oasis_options = options.get_options<db::OASISWriterOptions> ();
728+
oasis_options.write_cblocks = true;
729+
oasis_options.strict_mode = false;
730+
db::OASISWriter writer;
731+
writer.write (layout_org, out, options);
732+
}
733+
734+
db::Layout layout_read;
735+
736+
{
737+
tl::InputStream in (tmp_file);
738+
db::OASISReader reader (in);
739+
reader.read (layout_read);
740+
}
741+
742+
EXPECT_EQ (db::compare_layouts (layout_org, layout_read, db::layout_diff::f_verbose, 0), true);
743+
744+
}
745+
}

src/tl/tl/tlDeflate.cc

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "tlAssert.h"
2727

2828
#include <algorithm>
29+
#include <cstring>
2930

3031
#include <zlib.h>
3132

@@ -227,16 +228,22 @@ InflateFilter::InflateFilter (tl::InputStream &input)
227228
m_last_block (false),
228229
m_uncompressed_length (0) // this forces a new block on "process()"
229230
{
230-
for (size_t i = 0; i < sizeof (m_buffer) / sizeof (m_buffer [0]); ++i) {
231-
m_buffer[i] = 0;
232-
}
231+
// NOTE: the minimum buffer size of 65536 corresponds to the maximum block size
232+
// of the block repetition decoder
233+
m_blen = 65536; // initially
234+
235+
m_buffer = new char [m_blen];
236+
std::memset (m_buffer, 0, m_blen);
233237

234238
mp_dist_decoder = new HuffmannDecoder ();
235239
mp_lit_decoder = new HuffmannDecoder ();
236240
}
237241

238242
InflateFilter::~InflateFilter ()
239243
{
244+
delete[] m_buffer;
245+
m_buffer = 0;
246+
m_blen = 0;
240247
delete mp_dist_decoder;
241248
mp_dist_decoder = 0;
242249
delete mp_lit_decoder;
@@ -246,9 +253,36 @@ InflateFilter::~InflateFilter ()
246253
const char *
247254
InflateFilter::get (size_t n)
248255
{
249-
tl_assert (n < sizeof (m_buffer) / 2);
256+
size_t blen = m_blen;
257+
while (n >= blen / 2) {
258+
blen *= 2;
259+
}
260+
261+
// buffer needs to be enlarged - reallocate
262+
if (blen != m_blen) {
263+
264+
// NOTE: the deflate implementation actually looks back past the read pointer
265+
// (in put_byte_dist), so we have to maintain the bytes between m_b_read
266+
// and m_b_insert too.
267+
268+
char *new_buffer = new char[blen];
269+
270+
// place the current block twice at start and end of the block
271+
std::memcpy (new_buffer, m_buffer, m_blen);
272+
std::memcpy (new_buffer + blen - m_blen, m_buffer, m_blen);
273+
274+
// adjust read pointer if the stored byte array wrapped around the buffer
275+
if (m_b_insert < m_b_read) {
276+
m_b_read += blen - m_blen;
277+
}
278+
279+
delete[] m_buffer;
280+
m_buffer = new_buffer;
281+
m_blen = blen;
282+
283+
}
250284

251-
while ((m_b_insert + sizeof (m_buffer) - m_b_read) % sizeof (m_buffer) < n) {
285+
while ((m_b_insert + m_blen - m_b_read) % m_blen < n) {
252286
if (! process ()) {
253287
throw tl::Exception (tl::to_string (tr ("Unexpected end of file (DEFLATE implementation)")));
254288
}
@@ -257,14 +291,14 @@ InflateFilter::get (size_t n)
257291
tl_assert (m_b_read != m_b_insert);
258292

259293
// ensure the block is accessible as a coherent chunk:
260-
if (m_b_read + n >= sizeof (m_buffer)) {
261-
std::rotate (m_buffer, m_buffer + m_b_read, m_buffer + sizeof (m_buffer));
262-
m_b_insert = (m_b_insert - m_b_read + sizeof (m_buffer)) % sizeof (m_buffer);
294+
if (m_b_read + n >= m_blen) {
295+
std::rotate (m_buffer, m_buffer + m_b_read, m_buffer + m_blen);
296+
m_b_insert = (m_b_insert - m_b_read + m_blen) % m_blen;
263297
m_b_read = 0;
264298
}
265299

266300
const char *r = m_buffer + m_b_read;
267-
m_b_read = (m_b_read + n) % sizeof (m_buffer);
301+
m_b_read = (m_b_read + n) % m_blen;
268302
return r;
269303
}
270304

@@ -290,13 +324,16 @@ void
290324
InflateFilter::put_byte (char b)
291325
{
292326
m_buffer [m_b_insert] = b;
293-
m_b_insert = (m_b_insert + 1) % sizeof (m_buffer);
327+
m_b_insert = (m_b_insert + 1) % m_blen;
328+
// buffer overrun
329+
tl_assert (m_b_insert != m_b_read);
294330
}
295331

296332
void
297333
InflateFilter::put_byte_dist (unsigned int d)
298334
{
299-
put_byte (m_buffer [(m_b_insert - d) % sizeof (m_buffer)]);
335+
tl_assert (d < m_blen);
336+
put_byte (m_buffer [(m_b_insert + m_blen - d) % m_blen]);
300337
}
301338

302339
bool

src/tl/tl/tlDeflate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ class TL_PUBLIC InflateFilter
232232
private:
233233
BitStream m_input;
234234

235-
char m_buffer[65536];
235+
char *m_buffer;
236+
size_t m_blen;
236237
unsigned int m_b_insert;
237238
unsigned int m_b_read;
238239
bool m_at_end;

0 commit comments

Comments
 (0)