Eliminate undefined behavior

This commit is contained in:
topjohnwu 2020-01-06 05:30:57 +08:00
parent bce777d7c6
commit 2262af728e

View File

@ -380,11 +380,11 @@ class LZ4_decoder : public cpr_stream {
public: public:
explicit LZ4_decoder(stream_ptr &&base) explicit LZ4_decoder(stream_ptr &&base)
: cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]), : cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]),
buffer(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {} buf(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {}
~LZ4_decoder() override { ~LZ4_decoder() override {
delete[] out_buf; delete[] out_buf;
delete[] buffer; delete[] buf;
} }
int write(const void *in, size_t size) override { int write(const void *in, size_t size) override {
@ -396,20 +396,26 @@ public:
size -= 4; size -= 4;
init = true; init = true;
} }
int write; for (int consumed; size != 0;) {
size_t consumed;
do {
if (block_sz == 0) { if (block_sz == 0) {
block_sz = *((unsigned *) inbuf); if (buf_off + size >= sizeof(block_sz)) {
inbuf += sizeof(unsigned); consumed = sizeof(block_sz) - buf_off;
size -= sizeof(unsigned); memcpy(buf + buf_off, inbuf, consumed);
memcpy(&block_sz, buf, sizeof(block_sz));
buf_off = 0;
} else {
consumed = size;
memcpy(buf + buf_off, inbuf, size);
}
inbuf += consumed;
size -= consumed;
} else if (buf_off + size >= block_sz) { } else if (buf_off + size >= block_sz) {
consumed = block_sz - buf_off; consumed = block_sz - buf_off;
memcpy(buffer + buf_off, inbuf, consumed); memcpy(buf + buf_off, inbuf, consumed);
inbuf += consumed; inbuf += consumed;
size -= consumed; size -= consumed;
write = LZ4_decompress_safe(buffer, out_buf, block_sz, LZ4_UNCOMPRESSED); int write = LZ4_decompress_safe(buf, out_buf, block_sz, LZ4_UNCOMPRESSED);
if (write < 0) { if (write < 0) {
LOGW("LZ4HC decompression failure (%d)\n", write); LOGW("LZ4HC decompression failure (%d)\n", write);
return -1; return -1;
@ -421,17 +427,17 @@ public:
block_sz = 0; block_sz = 0;
} else { } else {
// Copy to internal buffer // Copy to internal buffer
memcpy(buffer + buf_off, inbuf, size); memcpy(buf + buf_off, inbuf, size);
buf_off += size; buf_off += size;
size = 0; break;
}
} }
} while (size != 0);
return ret; return ret;
} }
private: private:
char *out_buf; char *out_buf;
char *buffer; char *buf;
bool init; bool init;
unsigned block_sz; unsigned block_sz;
int buf_off; int buf_off;