mirror of https://github.com/KLayout/klayout.git
Cap PixelBuffer.from_bytes dimensions at 64k x 64k
Following review feedback, the reader now rejects a header claiming a
width or height beyond 65536, guarding against malformed byte streams
that would otherwise trigger an unreasonable allocation. The writer
stays full 32-bit ('unlimited'), and native little-endian order and the
transparency mask are kept as-is. Adds Ruby and Python tests for the
oversized-header rejection.
Ref: https://github.com/KLayout/klayout/pull/2387#issuecomment-4984941409
This commit is contained in:
parent
2fa7b24345
commit
9a606ec4e9
|
|
@ -146,6 +146,12 @@ static tl::PixelBuffer pixel_buffer_from_bytes (const std::vector<char> &data)
|
||||||
memcpy (&w, data.data (), 4);
|
memcpy (&w, data.data (), 4);
|
||||||
memcpy (&h, data.data () + 4, 4);
|
memcpy (&h, data.data () + 4, 4);
|
||||||
}
|
}
|
||||||
|
// sanity guard against malformed headers: reader caps dimensions at 64k x 64k
|
||||||
|
// (generous for finely-resolved drawings), writer stays full 32-bit
|
||||||
|
const uint32_t max_dim = 65536;
|
||||||
|
if (w > max_dim || h > max_dim) {
|
||||||
|
throw tl::Exception (tl::to_string (tr ("Invalid PixelBuffer byte stream: width or height exceeds the 65536 x 65536 limit")));
|
||||||
|
}
|
||||||
if (data.size () != 8 + (size_t) w * (size_t) h * 4) {
|
if (data.size () != 8 + (size_t) w * (size_t) h * 4) {
|
||||||
throw tl::Exception (tl::to_string (tr ("Invalid PixelBuffer byte stream: length does not match the width and height in the header")));
|
throw tl::Exception (tl::to_string (tr ("Invalid PixelBuffer byte stream: length does not match the width and height in the header")));
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +235,8 @@ Class<tl::PixelBuffer> decl_PixelBuffer ("lay", "PixelBuffer",
|
||||||
gsi::method ("from_bytes", &pixel_buffer_from_bytes, gsi::arg ("data"),
|
gsi::method ("from_bytes", &pixel_buffer_from_bytes, gsi::arg ("data"),
|
||||||
"@brief Reconstructs a pixel buffer from a byte stream produced by \\to_bytes\n"
|
"@brief Reconstructs a pixel buffer from a byte stream produced by \\to_bytes\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The width and height are taken from the header and the stream length is checked against them.\n"
|
"The width and height are taken from the header and the stream length is checked against them. "
|
||||||
|
"The dimensions are capped at 65536 x 65536; a header exceeding this limit raises an error.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been added in version 0.30.10."
|
"This method has been added in version 0.30.10."
|
||||||
) +
|
) +
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,10 @@ class LAYPixelBufferTests(unittest.TestCase):
|
||||||
with self.assertRaises(Exception):
|
with self.assertRaises(Exception):
|
||||||
pya.PixelBuffer.from_bytes(data[:-4])
|
pya.PixelBuffer.from_bytes(data[:-4])
|
||||||
|
|
||||||
|
# a header beyond the 64k x 64k limit is rejected
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
pya.PixelBuffer.from_bytes(struct.pack("=II", 65537, 1))
|
||||||
|
|
||||||
|
|
||||||
# run unit tests
|
# run unit tests
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,15 @@ class LAYPixelBuffer_TestClass < TestBase
|
||||||
end
|
end
|
||||||
assert_equal(error, true)
|
assert_equal(error, true)
|
||||||
|
|
||||||
|
# a header beyond the 64k x 64k limit is rejected
|
||||||
|
error = false
|
||||||
|
begin
|
||||||
|
RBA::PixelBuffer.from_bytes([ 65537, 1 ].pack("VV"))
|
||||||
|
rescue
|
||||||
|
error = true
|
||||||
|
end
|
||||||
|
assert_equal(error, true)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_11
|
def test_11
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue