Skip to content

Commit c241db9

Browse files
committed
Improve handling of very large length values during read/write
1 parent 59ed835 commit c241db9

3 files changed

Lines changed: 54 additions & 13 deletions

File tree

src/io/CompressedInputStream.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,11 @@ int CompressedInputStream::_get(int inc)
427427

428428
istream& CompressedInputStream::read(char* data, streamsize length)
429429
{
430-
int remaining = int(length);
431-
432-
if (remaining < 0)
430+
if (length < 0)
433431
throw ios_base::failure("Invalid buffer size");
434432

433+
streamsize remaining = length;
434+
435435
_gcount = 0;
436436

437437
while (remaining > 0) {
@@ -487,11 +487,11 @@ istream& CompressedInputStream::read(char* data, streamsize length)
487487

488488
}
489489

490-
const int lenChunk = min(remaining, int(_available));
490+
const streamsize lenChunk = min(remaining, streamsize(_available));
491491

492492
if (lenChunk > 0) {
493-
memcpy(&data[_gcount], &_buffers[_bufferId]->_array[_buffers[_bufferId]->_index], lenChunk);
494-
_buffers[_bufferId]->_index += lenChunk;
493+
memcpy(&data[_gcount], &_buffers[_bufferId]->_array[_buffers[_bufferId]->_index], size_t(lenChunk));
494+
_buffers[_bufferId]->_index += int(lenChunk);
495495
_gcount += lenChunk;
496496
remaining -= lenChunk;
497497
_available -= lenChunk;

src/io/CompressedOutputStream.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,18 @@ bool CompressedOutputStream::removeListener(Listener<Event>& bl)
361361

362362
ostream& CompressedOutputStream::write(const char* data, streamsize length)
363363
{
364-
int off = 0;
365-
int remaining = int(length);
366-
367-
if (remaining < 0)
364+
if (length < 0)
368365
throw IOException("Invalid buffer size");
369366

367+
streamsize off = 0;
368+
streamsize remaining = length;
369+
370370
while (remaining > 0) {
371-
const int lenChunk = min(remaining, _bufferThreshold - _buffers[_bufferId]->_index);
371+
const streamsize lenChunk = min(remaining, streamsize(_bufferThreshold - _buffers[_bufferId]->_index));
372372

373373
if (lenChunk > 0) {
374-
memcpy(&_buffers[_bufferId]->_array[_buffers[_bufferId]->_index], &data[off], lenChunk);
375-
_buffers[_bufferId]->_index += lenChunk;
374+
memcpy(&_buffers[_bufferId]->_array[_buffers[_bufferId]->_index], &data[off], size_t(lenChunk));
375+
_buffers[_bufferId]->_index += int(lenChunk);
376376
off += lenChunk;
377377
remaining -= lenChunk;
378378

src/test/TestCompressedStream.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616
#include <cstdio>
1717
#include <fstream>
1818
#include <iostream>
19+
#include <limits>
1920
#include "../io/CompressedInputStream.hpp"
2021
#include "../io/CompressedOutputStream.hpp"
2122
#include "../io/IOException.hpp"
@@ -202,6 +203,43 @@ uint64 compress5(kanzi::byte block[], uint length)
202203
return res;
203204
}
204205

206+
uint64 compress6(kanzi::byte block[])
207+
{
208+
CompressedOutputStream* cos = nullptr;
209+
CompressedInputStream* cis = nullptr;
210+
uint64 res;
211+
212+
try {
213+
cout << "Test - large read request does not overflow streamsize" << endl;
214+
stringbuf buffer;
215+
iostream ios(&buffer);
216+
cos = new CompressedOutputStream(ios, 1, "HUFFMAN", "TEXT");
217+
cos->write((const char*)block, 1);
218+
cos->close();
219+
ios.seekg(0);
220+
cis = new CompressedInputStream(ios, 1);
221+
char decoded[1] = { 0 };
222+
const streamsize requested = streamsize(numeric_limits<int>::max()) + streamsize(1);
223+
cis->read(decoded, requested);
224+
225+
if ((cis->gcount() != 1) || (decoded[0] != char(block[0]))) {
226+
cout << "Failure: invalid read result for large request" << endl;
227+
res = 1;
228+
}
229+
else {
230+
res = 0;
231+
}
232+
}
233+
catch (const ios_base::failure& e) {
234+
cout << "Failure: unexpected exception " << e.what() << endl;
235+
res = 1;
236+
}
237+
238+
delete cos;
239+
delete cis;
240+
return res;
241+
}
242+
205243
int testCorrectness(int, const char*[])
206244
{
207245
// Test correctness
@@ -240,6 +278,9 @@ int testCorrectness(int, const char*[])
240278
cres = compress5(values, length);
241279
cout << ((cres == 0) ? "Success" : "Failure") << endl;
242280
res &= (cres == 0);
281+
cres = compress6(values);
282+
cout << ((cres == 0) ? "Success" : "Failure") << endl;
283+
res &= (cres == 0);
243284
}
244285
}
245286

0 commit comments

Comments
 (0)