In shippable code, favor smart pointers (fixes #235)

Use PointerHolder in several places where manually memory allocation
and deallocation were being used. This helps to protect against memory
leaks when exceptions are thrown in surprising places.
This commit is contained in:
Jay Berkenbilt 2019-06-22 14:24:49 -04:00
parent 1240047528
commit 6c39aa8763
18 changed files with 81 additions and 92 deletions

View File

@ -1,5 +1,8 @@
2019-06-22 Jay Berkenbilt <ejb@ql.org> 2019-06-22 Jay Berkenbilt <ejb@ql.org>
* Favor PointerHolder over manual memory allocation in shippable
code where possible. Fixes #235.
* If pkg-config is available, use it to local libjpeg and zlib. If * If pkg-config is available, use it to local libjpeg and zlib. If
not, fall back to old behavior. Fixes #324. not, fall back to old behavior. Fixes #324.

View File

@ -82,7 +82,7 @@ class ClosedFileInputSource: public InputSource
std::string filename; std::string filename;
qpdf_offset_t offset; qpdf_offset_t offset;
FileInputSource* fis; PointerHolder<FileInputSource> fis;
bool stay_open; bool stay_open;
}; };
PointerHolder<Members> m; PointerHolder<Members> m;

View File

@ -58,7 +58,7 @@ class Pl_Flate: public Pipeline
Members(size_t out_bufsize, action_e action); Members(size_t out_bufsize, action_e action);
Members(Members const&); Members(Members const&);
unsigned char* outbuf; PointerHolder<unsigned char> outbuf;
size_t out_bufsize; size_t out_bufsize;
action_e action; action_e action;
bool initialized; bool initialized;

View File

@ -4,14 +4,12 @@
ClosedFileInputSource::Members::Members(char const* filename) : ClosedFileInputSource::Members::Members(char const* filename) :
filename(filename), filename(filename),
offset(0), offset(0),
fis(0),
stay_open(false) stay_open(false)
{ {
} }
ClosedFileInputSource::Members::~Members() ClosedFileInputSource::Members::~Members()
{ {
delete fis;
} }
ClosedFileInputSource::ClosedFileInputSource(char const* filename) : ClosedFileInputSource::ClosedFileInputSource(char const* filename) :
@ -26,7 +24,7 @@ ClosedFileInputSource::~ClosedFileInputSource()
void void
ClosedFileInputSource::before() ClosedFileInputSource::before()
{ {
if (0 == this->m->fis) if (0 == this->m->fis.getPointer())
{ {
this->m->fis = new FileInputSource(); this->m->fis = new FileInputSource();
this->m->fis->setFilename(this->m->filename.c_str()); this->m->fis->setFilename(this->m->filename.c_str());
@ -44,7 +42,6 @@ ClosedFileInputSource::after()
{ {
return; return;
} }
delete this->m->fis;
this->m->fis = 0; this->m->fis = 0;
} }
@ -84,7 +81,7 @@ void
ClosedFileInputSource::rewind() ClosedFileInputSource::rewind()
{ {
this->m->offset = 0; this->m->offset = 0;
if (this->m->fis) if (this->m->fis.getPointer())
{ {
this->m->fis->rewind(); this->m->fis->rewind();
} }
@ -112,7 +109,7 @@ void
ClosedFileInputSource::stayOpen(bool val) ClosedFileInputSource::stayOpen(bool val)
{ {
this->m->stay_open = val; this->m->stay_open = val;
if ((! val) && this->m->fis) if ((! val) && this->m->fis.getPointer())
{ {
after(); after();
} }

View File

@ -25,29 +25,31 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
{ {
size_t keybits = 8 * key_bytes; size_t keybits = 8 * key_bytes;
assert(key_bytes == KEYLENGTH(keybits)); assert(key_bytes == KEYLENGTH(keybits));
this->key = new unsigned char[key_bytes]; this->key = PointerHolder<unsigned char>(
this->rk = new uint32_t[RKLENGTH(keybits)]; true, new unsigned char[key_bytes]);
this->rk = PointerHolder<uint32_t>(
true, new uint32_t[RKLENGTH(keybits)]);
size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t); size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
std::memcpy(this->key, key, key_bytes); std::memcpy(this->key.getPointer(), key, key_bytes);
std::memset(this->rk, 0, rk_bytes); std::memset(this->rk.getPointer(), 0, rk_bytes);
std::memset(this->inbuf, 0, this->buf_size); std::memset(this->inbuf, 0, this->buf_size);
std::memset(this->outbuf, 0, this->buf_size); std::memset(this->outbuf, 0, this->buf_size);
std::memset(this->cbc_block, 0, this->buf_size); std::memset(this->cbc_block, 0, this->buf_size);
if (encrypt) if (encrypt)
{ {
this->nrounds = rijndaelSetupEncrypt(this->rk, this->key, keybits); this->nrounds = rijndaelSetupEncrypt(
this->rk.getPointer(), this->key.getPointer(), keybits);
} }
else else
{ {
this->nrounds = rijndaelSetupDecrypt(this->rk, this->key, keybits); this->nrounds = rijndaelSetupDecrypt(
this->rk.getPointer(), this->key.getPointer(), keybits);
} }
assert(this->nrounds == NROUNDS(keybits)); assert(this->nrounds == NROUNDS(keybits));
} }
Pl_AES_PDF::~Pl_AES_PDF() Pl_AES_PDF::~Pl_AES_PDF()
{ {
delete [] this->key;
delete [] this->rk;
} }
void void
@ -222,7 +224,8 @@ Pl_AES_PDF::flush(bool strip_padding)
this->inbuf[i] ^= this->cbc_block[i]; this->inbuf[i] ^= this->cbc_block[i];
} }
} }
rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); rijndaelEncrypt(this->rk.getPointer(),
this->nrounds, this->inbuf, this->outbuf);
if (this->cbc_mode) if (this->cbc_mode)
{ {
memcpy(this->cbc_block, this->outbuf, this->buf_size); memcpy(this->cbc_block, this->outbuf, this->buf_size);
@ -230,7 +233,8 @@ Pl_AES_PDF::flush(bool strip_padding)
} }
else else
{ {
rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf); rijndaelDecrypt(this->rk.getPointer(),
this->nrounds, this->inbuf, this->outbuf);
if (this->cbc_mode) if (this->cbc_mode)
{ {
for (unsigned int i = 0; i < this->buf_size; ++i) for (unsigned int i = 0; i < this->buf_size; ++i)

View File

@ -13,7 +13,8 @@ Pl_Flate::Members::Members(size_t out_bufsize,
initialized(false), initialized(false),
zdata(0) zdata(0)
{ {
this->outbuf = new unsigned char[out_bufsize]; this->outbuf = PointerHolder<unsigned char>(
true, new unsigned char[out_bufsize]);
// Indirect through zdata to reach the z_stream so we don't have // Indirect through zdata to reach the z_stream so we don't have
// to include zlib.h in Pl_Flate.hh. This means people using // to include zlib.h in Pl_Flate.hh. This means people using
// shared library versions of qpdf don't have to have zlib // shared library versions of qpdf don't have to have zlib
@ -34,15 +35,12 @@ Pl_Flate::Members::Members(size_t out_bufsize,
zstream.opaque = 0; zstream.opaque = 0;
zstream.next_in = 0; zstream.next_in = 0;
zstream.avail_in = 0; zstream.avail_in = 0;
zstream.next_out = this->outbuf; zstream.next_out = this->outbuf.getPointer();
zstream.avail_out = QIntC::to_uint(out_bufsize); zstream.avail_out = QIntC::to_uint(out_bufsize);
} }
Pl_Flate::Members::~Members() Pl_Flate::Members::~Members()
{ {
delete [] this->outbuf;
this->outbuf = 0;
if (this->initialized) if (this->initialized)
{ {
z_stream& zstream = *(static_cast<z_stream*>(this->zdata)); z_stream& zstream = *(static_cast<z_stream*>(this->zdata));
@ -74,7 +72,7 @@ Pl_Flate::~Pl_Flate()
void void
Pl_Flate::write(unsigned char* data, size_t len) Pl_Flate::write(unsigned char* data, size_t len)
{ {
if (this->m->outbuf == 0) if (this->m->outbuf.getPointer() == 0)
{ {
throw std::logic_error( throw std::logic_error(
this->identifier + this->identifier +
@ -186,8 +184,8 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out); QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out);
if (ready > 0) if (ready > 0)
{ {
this->getNext()->write(this->m->outbuf, ready); this->getNext()->write(this->m->outbuf.getPointer(), ready);
zstream.next_out = this->m->outbuf; zstream.next_out = this->m->outbuf.getPointer();
zstream.avail_out = QIntC::to_uint(this->m->out_bufsize); zstream.avail_out = QIntC::to_uint(this->m->out_bufsize);
} }
} }
@ -205,7 +203,7 @@ Pl_Flate::finish()
{ {
try try
{ {
if (this->m->outbuf) if (this->m->outbuf.getPointer())
{ {
if (this->m->initialized) if (this->m->initialized)
{ {
@ -226,7 +224,6 @@ Pl_Flate::finish()
checkError("End", err); checkError("End", err);
} }
delete [] this->m->outbuf;
this->m->outbuf = 0; this->m->outbuf = 0;
} }
} }

View File

@ -45,12 +45,14 @@ Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
"PNGFilter created with invalid columns value"); "PNGFilter created with invalid columns value");
} }
this->bytes_per_row = bpr & UINT_MAX; this->bytes_per_row = bpr & UINT_MAX;
this->buf1 = new unsigned char[this->bytes_per_row + 1]; this->buf1 = PointerHolder<unsigned char>(
this->buf2 = new unsigned char[this->bytes_per_row + 1]; true, new unsigned char[this->bytes_per_row + 1]);
memset(this->buf1, 0, this->bytes_per_row + 1); this->buf2 = PointerHolder<unsigned char>(
memset(this->buf2, 0, this->bytes_per_row + 1); true, new unsigned char[this->bytes_per_row + 1]);
this->cur_row = this->buf1; memset(this->buf1.getPointer(), 0, this->bytes_per_row + 1);
this->prev_row = this->buf2; memset(this->buf2.getPointer(), 0, this->bytes_per_row + 1);
this->cur_row = this->buf1.getPointer();
this->prev_row = this->buf2.getPointer();
// number of bytes per incoming row // number of bytes per incoming row
this->incoming = (action == a_encode ? this->incoming = (action == a_encode ?
@ -60,8 +62,6 @@ Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
Pl_PNGFilter::~Pl_PNGFilter() Pl_PNGFilter::~Pl_PNGFilter()
{ {
delete [] buf1;
delete [] buf2;
} }
void void
@ -81,7 +81,7 @@ Pl_PNGFilter::write(unsigned char* data, size_t len)
// Swap rows // Swap rows
unsigned char* t = this->prev_row; unsigned char* t = this->prev_row;
this->prev_row = this->cur_row; this->prev_row = this->cur_row;
this->cur_row = t ? t : this->buf2; this->cur_row = t ? t : this->buf2.getPointer();
memset(this->cur_row, 0, this->bytes_per_row + 1); memset(this->cur_row, 0, this->bytes_per_row + 1);
left = this->incoming; left = this->incoming;
this->pos = 0; this->pos = 0;
@ -269,7 +269,7 @@ Pl_PNGFilter::finish()
processRow(); processRow();
} }
this->prev_row = 0; this->prev_row = 0;
this->cur_row = buf1; this->cur_row = buf1.getPointer();
this->pos = 0; this->pos = 0;
memset(this->cur_row, 0, this->bytes_per_row + 1); memset(this->cur_row, 0, this->bytes_per_row + 1);

View File

@ -8,19 +8,18 @@ Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next,
out_bufsize(out_bufsize), out_bufsize(out_bufsize),
rc4(key_data, key_len) rc4(key_data, key_len)
{ {
this->outbuf = new unsigned char[out_bufsize]; this->outbuf = PointerHolder<unsigned char>(
true, new unsigned char[out_bufsize]);
} }
Pl_RC4::~Pl_RC4() Pl_RC4::~Pl_RC4()
{ {
delete [] this->outbuf;
this->outbuf = 0;
} }
void void
Pl_RC4::write(unsigned char* data, size_t len) Pl_RC4::write(unsigned char* data, size_t len)
{ {
if (this->outbuf == 0) if (this->outbuf.getPointer() == 0)
{ {
throw std::logic_error( throw std::logic_error(
this->identifier + this->identifier +
@ -35,16 +34,15 @@ Pl_RC4::write(unsigned char* data, size_t len)
size_t bytes = size_t bytes =
(bytes_left < this->out_bufsize ? bytes_left : out_bufsize); (bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
bytes_left -= bytes; bytes_left -= bytes;
rc4.process(p, bytes, outbuf); rc4.process(p, bytes, outbuf.getPointer());
p += bytes; p += bytes;
getNext()->write(outbuf, bytes); getNext()->write(outbuf.getPointer(), bytes);
} }
} }
void void
Pl_RC4::finish() Pl_RC4::finish()
{ {
delete [] this->outbuf;
this->outbuf = 0; this->outbuf = 0;
this->getNext()->finish(); this->getNext()->finish();
} }

View File

@ -16,7 +16,6 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(char const* identifier, Pipeline* next,
columns(columns), columns(columns),
samples_per_pixel(samples_per_pixel), samples_per_pixel(samples_per_pixel),
bits_per_sample(bits_per_sample), bits_per_sample(bits_per_sample),
cur_row(0),
pos(0) pos(0)
{ {
if (samples_per_pixel < 1) if (samples_per_pixel < 1)
@ -38,13 +37,13 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(char const* identifier, Pipeline* next,
"TIFFPredictor created with invalid columns value"); "TIFFPredictor created with invalid columns value");
} }
this->bytes_per_row = bpr & UINT_MAX; this->bytes_per_row = bpr & UINT_MAX;
this->cur_row = new unsigned char[this->bytes_per_row]; this->cur_row = PointerHolder<unsigned char>(
memset(this->cur_row, 0, this->bytes_per_row); true, new unsigned char[this->bytes_per_row]);
memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
} }
Pl_TIFFPredictor::~Pl_TIFFPredictor() Pl_TIFFPredictor::~Pl_TIFFPredictor()
{ {
delete [] cur_row;
} }
void void
@ -55,20 +54,20 @@ Pl_TIFFPredictor::write(unsigned char* data, size_t len)
while (len >= left) while (len >= left)
{ {
// finish off current row // finish off current row
memcpy(this->cur_row + this->pos, data + offset, left); memcpy(this->cur_row.getPointer() + this->pos, data + offset, left);
offset += left; offset += left;
len -= left; len -= left;
processRow(); processRow();
// Prepare for next row // Prepare for next row
memset(this->cur_row, 0, this->bytes_per_row); memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
left = this->bytes_per_row; left = this->bytes_per_row;
this->pos = 0; this->pos = 0;
} }
if (len) if (len)
{ {
memcpy(this->cur_row + this->pos, data + offset, len); memcpy(this->cur_row.getPointer() + this->pos, data + offset, len);
} }
this->pos += len; this->pos += len;
} }
@ -79,7 +78,7 @@ Pl_TIFFPredictor::processRow()
QTC::TC("libtests", "Pl_TIFFPredictor processRow", QTC::TC("libtests", "Pl_TIFFPredictor processRow",
(action == a_decode ? 0 : 1)); (action == a_decode ? 0 : 1));
BitWriter bw(this->getNext()); BitWriter bw(this->getNext());
BitStream in(this->cur_row, this->bytes_per_row); BitStream in(this->cur_row.getPointer(), this->bytes_per_row);
std::vector<long long> prev; std::vector<long long> prev;
for (unsigned int i = 0; i < this->samples_per_pixel; ++i) for (unsigned int i = 0; i < this->samples_per_pixel; ++i)
{ {
@ -118,6 +117,6 @@ Pl_TIFFPredictor::finish()
processRow(); processRow();
} }
this->pos = 0; this->pos = 0;
memset(this->cur_row, 0, this->bytes_per_row); memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
getNext()->finish(); getNext()->finish();
} }

View File

@ -1835,21 +1835,21 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
this->m->cur_data_key.length()); this->m->cur_data_key.length());
pl.write(QUtil::unsigned_char_pointer(val), val.length()); pl.write(QUtil::unsigned_char_pointer(val), val.length());
pl.finish(); pl.finish();
Buffer* buf = bufpl.getBuffer(); PointerHolder<Buffer> buf = bufpl.getBuffer();
val = QPDF_String( val = QPDF_String(
std::string(reinterpret_cast<char*>(buf->getBuffer()), std::string(reinterpret_cast<char*>(buf->getBuffer()),
buf->getSize())).unparse(true); buf->getSize())).unparse(true);
delete buf;
} }
else else
{ {
char* tmp = QUtil::copy_string(val); PointerHolder<char> tmp_ph =
PointerHolder<char>(true, QUtil::copy_string(val));
char* tmp = tmp_ph.getPointer();
size_t vlen = val.length(); size_t vlen = val.length();
RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key), RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key),
QIntC::to_int(this->m->cur_data_key.length())); QIntC::to_int(this->m->cur_data_key.length()));
rc4.process(QUtil::unsigned_char_pointer(tmp), vlen); rc4.process(QUtil::unsigned_char_pointer(tmp), vlen);
val = QPDF_String(std::string(tmp, vlen)).unparse(); val = QPDF_String(std::string(tmp, vlen)).unparse();
delete [] tmp;
} }
} }
else else

View File

@ -204,7 +204,9 @@ iterate_rc4(unsigned char* data, size_t data_len,
unsigned char* okey, int key_len, unsigned char* okey, int key_len,
int iterations, bool reverse) int iterations, bool reverse)
{ {
unsigned char* key = new unsigned char[QIntC::to_size(key_len)]; PointerHolder<unsigned char> key_ph = PointerHolder<unsigned char>(
true, new unsigned char[QIntC::to_size(key_len)]);
unsigned char* key = key_ph.getPointer();
for (int i = 0; i < iterations; ++i) for (int i = 0; i < iterations; ++i)
{ {
int const xor_value = (reverse ? iterations - 1 - i : i); int const xor_value = (reverse ? iterations - 1 - i : i);
@ -215,7 +217,6 @@ iterate_rc4(unsigned char* data, size_t data_len,
RC4 rc4(key, QIntC::to_int(key_len)); RC4 rc4(key, QIntC::to_int(key_len));
rc4.process(data, data_len); rc4.process(data, data_len);
} }
delete [] key;
} }
static std::string static std::string

View File

@ -670,10 +670,9 @@ QUtil::get_env(std::string const& var, std::string* value)
if (value) if (value)
{ {
char* t = new char[len + 1]; PointerHolder<char> t = PointerHolder<char>(true, new char[len + 1]);
::GetEnvironmentVariable(var.c_str(), t, len); ::GetEnvironmentVariable(var.c_str(), t.getPointer(), len);
*value = t; *value = t.getPointer();
delete [] t;
} }
return true; return true;

View File

@ -22,8 +22,8 @@ struct _qpdf_data
_qpdf_data(); _qpdf_data();
~_qpdf_data(); ~_qpdf_data();
QPDF* qpdf; PointerHolder<QPDF> qpdf;
QPDFWriter* qpdf_writer; PointerHolder<QPDFWriter> qpdf_writer;
PointerHolder<QPDFExc> error; PointerHolder<QPDFExc> error;
_qpdf_error tmp_error; _qpdf_error tmp_error;
@ -36,22 +36,16 @@ struct _qpdf_data
unsigned long long size; unsigned long long size;
char const* password; char const* password;
bool write_memory; bool write_memory;
Buffer* output_buffer; PointerHolder<Buffer> output_buffer;
}; };
_qpdf_data::_qpdf_data() : _qpdf_data::_qpdf_data() :
qpdf(0), write_memory(false)
qpdf_writer(0),
write_memory(false),
output_buffer(0)
{ {
} }
_qpdf_data::~_qpdf_data() _qpdf_data::~_qpdf_data()
{ {
delete qpdf_writer;
delete qpdf;
delete output_buffer;
} }
// must set qpdf->filename and qpdf->password // must set qpdf->filename and qpdf->password
@ -451,14 +445,12 @@ QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf)
static void qpdf_init_write_internal(qpdf_data qpdf) static void qpdf_init_write_internal(qpdf_data qpdf)
{ {
if (qpdf->qpdf_writer) if (qpdf->qpdf_writer.getPointer())
{ {
QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times"); QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times");
delete qpdf->qpdf_writer;
qpdf->qpdf_writer = 0; qpdf->qpdf_writer = 0;
if (qpdf->output_buffer) if (qpdf->output_buffer.getPointer())
{ {
delete qpdf->output_buffer;
qpdf->output_buffer = 0; qpdf->output_buffer = 0;
qpdf->write_memory = false; qpdf->write_memory = false;
qpdf->filename = 0; qpdf->filename = 0;
@ -496,7 +488,7 @@ size_t qpdf_get_buffer_length(qpdf_data qpdf)
{ {
qpdf_get_buffer_internal(qpdf); qpdf_get_buffer_internal(qpdf);
size_t result = 0; size_t result = 0;
if (qpdf->output_buffer) if (qpdf->output_buffer.getPointer())
{ {
result = qpdf->output_buffer->getSize(); result = qpdf->output_buffer->getSize();
} }
@ -507,7 +499,7 @@ unsigned char const* qpdf_get_buffer(qpdf_data qpdf)
{ {
unsigned char const* result = 0; unsigned char const* result = 0;
qpdf_get_buffer_internal(qpdf); qpdf_get_buffer_internal(qpdf);
if (qpdf->output_buffer) if (qpdf->output_buffer.getPointer())
{ {
result = qpdf->output_buffer->getBuffer(); result = qpdf->output_buffer->getBuffer();
} }

View File

@ -55,8 +55,8 @@ class Pl_AES_PDF: public Pipeline
bool cbc_mode; bool cbc_mode;
bool first; bool first;
size_t offset; // offset into memory buffer size_t offset; // offset into memory buffer
unsigned char* key; PointerHolder<unsigned char> key;
uint32_t* rk; PointerHolder<uint32_t> rk;
unsigned char inbuf[buf_size]; unsigned char inbuf[buf_size];
unsigned char outbuf[buf_size]; unsigned char outbuf[buf_size];
unsigned char cbc_block[buf_size]; unsigned char cbc_block[buf_size];

View File

@ -41,10 +41,10 @@ class Pl_PNGFilter: public Pipeline
action_e action; action_e action;
unsigned int bytes_per_row; unsigned int bytes_per_row;
unsigned int bytes_per_pixel; unsigned int bytes_per_pixel;
unsigned char* cur_row; unsigned char* cur_row; // points to buf1 or buf2
unsigned char* prev_row; unsigned char* prev_row; // points to buf1 or buf2
unsigned char* buf1; PointerHolder<unsigned char> buf1;
unsigned char* buf2; PointerHolder<unsigned char> buf2;
size_t pos; size_t pos;
size_t incoming; size_t incoming;
}; };

View File

@ -24,7 +24,7 @@ class Pl_RC4: public Pipeline
virtual void finish(); virtual void finish();
private: private:
unsigned char* outbuf; PointerHolder<unsigned char> outbuf;
size_t out_bufsize; size_t out_bufsize;
RC4 rc4; RC4 rc4;
}; };

View File

@ -32,7 +32,7 @@ class Pl_TIFFPredictor: public Pipeline
unsigned int bytes_per_row; unsigned int bytes_per_row;
unsigned int samples_per_pixel; unsigned int samples_per_pixel;
unsigned int bits_per_sample; unsigned int bits_per_sample;
unsigned char* cur_row; PointerHolder<unsigned char> cur_row;
size_t pos; size_t pos;
}; };

View File

@ -61,8 +61,9 @@ int main(int argc, char* argv[])
QUtil::binary_stdout(); QUtil::binary_stdout();
QUtil::binary_stdin(); QUtil::binary_stdin();
Pl_StdioFile* out = new Pl_StdioFile("stdout", stdout); PointerHolder<Pl_StdioFile> out = new Pl_StdioFile("stdout", stdout);
Pl_Flate* flate = new Pl_Flate("flate", out, action); PointerHolder<Pl_Flate> flate =
new Pl_Flate("flate", out.getPointer(), action);
try try
{ {
@ -81,8 +82,6 @@ int main(int argc, char* argv[])
} }
} }
flate->finish(); flate->finish();
delete flate;
delete out;
} }
catch (std::exception& e) catch (std::exception& e)
{ {