Commit 6c39aa87638f7a6f96a97627ac112fb2022bd3a7

Authored by Jay Berkenbilt
1 parent 12400475

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.
ChangeLog
1 1 2019-06-22 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Favor PointerHolder over manual memory allocation in shippable
  4 + code where possible. Fixes #235.
  5 +
3 6 * If pkg-config is available, use it to local libjpeg and zlib. If
4 7 not, fall back to old behavior. Fixes #324.
5 8  
... ...
include/qpdf/ClosedFileInputSource.hh
... ... @@ -82,7 +82,7 @@ class ClosedFileInputSource: public InputSource
82 82  
83 83 std::string filename;
84 84 qpdf_offset_t offset;
85   - FileInputSource* fis;
  85 + PointerHolder<FileInputSource> fis;
86 86 bool stay_open;
87 87 };
88 88 PointerHolder<Members> m;
... ...
include/qpdf/Pl_Flate.hh
... ... @@ -58,7 +58,7 @@ class Pl_Flate: public Pipeline
58 58 Members(size_t out_bufsize, action_e action);
59 59 Members(Members const&);
60 60  
61   - unsigned char* outbuf;
  61 + PointerHolder<unsigned char> outbuf;
62 62 size_t out_bufsize;
63 63 action_e action;
64 64 bool initialized;
... ...
libqpdf/ClosedFileInputSource.cc
... ... @@ -4,14 +4,12 @@
4 4 ClosedFileInputSource::Members::Members(char const* filename) :
5 5 filename(filename),
6 6 offset(0),
7   - fis(0),
8 7 stay_open(false)
9 8 {
10 9 }
11 10  
12 11 ClosedFileInputSource::Members::~Members()
13 12 {
14   - delete fis;
15 13 }
16 14  
17 15 ClosedFileInputSource::ClosedFileInputSource(char const* filename) :
... ... @@ -26,7 +24,7 @@ ClosedFileInputSource::~ClosedFileInputSource()
26 24 void
27 25 ClosedFileInputSource::before()
28 26 {
29   - if (0 == this->m->fis)
  27 + if (0 == this->m->fis.getPointer())
30 28 {
31 29 this->m->fis = new FileInputSource();
32 30 this->m->fis->setFilename(this->m->filename.c_str());
... ... @@ -44,7 +42,6 @@ ClosedFileInputSource::after()
44 42 {
45 43 return;
46 44 }
47   - delete this->m->fis;
48 45 this->m->fis = 0;
49 46 }
50 47  
... ... @@ -84,7 +81,7 @@ void
84 81 ClosedFileInputSource::rewind()
85 82 {
86 83 this->m->offset = 0;
87   - if (this->m->fis)
  84 + if (this->m->fis.getPointer())
88 85 {
89 86 this->m->fis->rewind();
90 87 }
... ... @@ -112,7 +109,7 @@ void
112 109 ClosedFileInputSource::stayOpen(bool val)
113 110 {
114 111 this->m->stay_open = val;
115   - if ((! val) && this->m->fis)
  112 + if ((! val) && this->m->fis.getPointer())
116 113 {
117 114 after();
118 115 }
... ...
libqpdf/Pl_AES_PDF.cc
... ... @@ -25,29 +25,31 @@ Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
25 25 {
26 26 size_t keybits = 8 * key_bytes;
27 27 assert(key_bytes == KEYLENGTH(keybits));
28   - this->key = new unsigned char[key_bytes];
29   - this->rk = new uint32_t[RKLENGTH(keybits)];
  28 + this->key = PointerHolder<unsigned char>(
  29 + true, new unsigned char[key_bytes]);
  30 + this->rk = PointerHolder<uint32_t>(
  31 + true, new uint32_t[RKLENGTH(keybits)]);
30 32 size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
31   - std::memcpy(this->key, key, key_bytes);
32   - std::memset(this->rk, 0, rk_bytes);
  33 + std::memcpy(this->key.getPointer(), key, key_bytes);
  34 + std::memset(this->rk.getPointer(), 0, rk_bytes);
33 35 std::memset(this->inbuf, 0, this->buf_size);
34 36 std::memset(this->outbuf, 0, this->buf_size);
35 37 std::memset(this->cbc_block, 0, this->buf_size);
36 38 if (encrypt)
37 39 {
38   - this->nrounds = rijndaelSetupEncrypt(this->rk, this->key, keybits);
  40 + this->nrounds = rijndaelSetupEncrypt(
  41 + this->rk.getPointer(), this->key.getPointer(), keybits);
39 42 }
40 43 else
41 44 {
42   - this->nrounds = rijndaelSetupDecrypt(this->rk, this->key, keybits);
  45 + this->nrounds = rijndaelSetupDecrypt(
  46 + this->rk.getPointer(), this->key.getPointer(), keybits);
43 47 }
44 48 assert(this->nrounds == NROUNDS(keybits));
45 49 }
46 50  
47 51 Pl_AES_PDF::~Pl_AES_PDF()
48 52 {
49   - delete [] this->key;
50   - delete [] this->rk;
51 53 }
52 54  
53 55 void
... ... @@ -222,7 +224,8 @@ Pl_AES_PDF::flush(bool strip_padding)
222 224 this->inbuf[i] ^= this->cbc_block[i];
223 225 }
224 226 }
225   - rijndaelEncrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
  227 + rijndaelEncrypt(this->rk.getPointer(),
  228 + this->nrounds, this->inbuf, this->outbuf);
226 229 if (this->cbc_mode)
227 230 {
228 231 memcpy(this->cbc_block, this->outbuf, this->buf_size);
... ... @@ -230,7 +233,8 @@ Pl_AES_PDF::flush(bool strip_padding)
230 233 }
231 234 else
232 235 {
233   - rijndaelDecrypt(this->rk, this->nrounds, this->inbuf, this->outbuf);
  236 + rijndaelDecrypt(this->rk.getPointer(),
  237 + this->nrounds, this->inbuf, this->outbuf);
234 238 if (this->cbc_mode)
235 239 {
236 240 for (unsigned int i = 0; i < this->buf_size; ++i)
... ...
libqpdf/Pl_Flate.cc
... ... @@ -13,7 +13,8 @@ Pl_Flate::Members::Members(size_t out_bufsize,
13 13 initialized(false),
14 14 zdata(0)
15 15 {
16   - this->outbuf = new unsigned char[out_bufsize];
  16 + this->outbuf = PointerHolder<unsigned char>(
  17 + true, new unsigned char[out_bufsize]);
17 18 // Indirect through zdata to reach the z_stream so we don't have
18 19 // to include zlib.h in Pl_Flate.hh. This means people using
19 20 // shared library versions of qpdf don't have to have zlib
... ... @@ -34,15 +35,12 @@ Pl_Flate::Members::Members(size_t out_bufsize,
34 35 zstream.opaque = 0;
35 36 zstream.next_in = 0;
36 37 zstream.avail_in = 0;
37   - zstream.next_out = this->outbuf;
  38 + zstream.next_out = this->outbuf.getPointer();
38 39 zstream.avail_out = QIntC::to_uint(out_bufsize);
39 40 }
40 41  
41 42 Pl_Flate::Members::~Members()
42 43 {
43   - delete [] this->outbuf;
44   - this->outbuf = 0;
45   -
46 44 if (this->initialized)
47 45 {
48 46 z_stream& zstream = *(static_cast<z_stream*>(this->zdata));
... ... @@ -74,7 +72,7 @@ Pl_Flate::~Pl_Flate()
74 72 void
75 73 Pl_Flate::write(unsigned char* data, size_t len)
76 74 {
77   - if (this->m->outbuf == 0)
  75 + if (this->m->outbuf.getPointer() == 0)
78 76 {
79 77 throw std::logic_error(
80 78 this->identifier +
... ... @@ -186,8 +184,8 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
186 184 QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out);
187 185 if (ready > 0)
188 186 {
189   - this->getNext()->write(this->m->outbuf, ready);
190   - zstream.next_out = this->m->outbuf;
  187 + this->getNext()->write(this->m->outbuf.getPointer(), ready);
  188 + zstream.next_out = this->m->outbuf.getPointer();
191 189 zstream.avail_out = QIntC::to_uint(this->m->out_bufsize);
192 190 }
193 191 }
... ... @@ -205,7 +203,7 @@ Pl_Flate::finish()
205 203 {
206 204 try
207 205 {
208   - if (this->m->outbuf)
  206 + if (this->m->outbuf.getPointer())
209 207 {
210 208 if (this->m->initialized)
211 209 {
... ... @@ -226,7 +224,6 @@ Pl_Flate::finish()
226 224 checkError("End", err);
227 225 }
228 226  
229   - delete [] this->m->outbuf;
230 227 this->m->outbuf = 0;
231 228 }
232 229 }
... ...
libqpdf/Pl_PNGFilter.cc
... ... @@ -45,12 +45,14 @@ Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
45 45 "PNGFilter created with invalid columns value");
46 46 }
47 47 this->bytes_per_row = bpr & UINT_MAX;
48   - this->buf1 = new unsigned char[this->bytes_per_row + 1];
49   - this->buf2 = new unsigned char[this->bytes_per_row + 1];
50   - memset(this->buf1, 0, this->bytes_per_row + 1);
51   - memset(this->buf2, 0, this->bytes_per_row + 1);
52   - this->cur_row = this->buf1;
53   - this->prev_row = this->buf2;
  48 + this->buf1 = PointerHolder<unsigned char>(
  49 + true, new unsigned char[this->bytes_per_row + 1]);
  50 + this->buf2 = PointerHolder<unsigned char>(
  51 + true, new unsigned char[this->bytes_per_row + 1]);
  52 + memset(this->buf1.getPointer(), 0, this->bytes_per_row + 1);
  53 + memset(this->buf2.getPointer(), 0, this->bytes_per_row + 1);
  54 + this->cur_row = this->buf1.getPointer();
  55 + this->prev_row = this->buf2.getPointer();
54 56  
55 57 // number of bytes per incoming row
56 58 this->incoming = (action == a_encode ?
... ... @@ -60,8 +62,6 @@ Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
60 62  
61 63 Pl_PNGFilter::~Pl_PNGFilter()
62 64 {
63   - delete [] buf1;
64   - delete [] buf2;
65 65 }
66 66  
67 67 void
... ... @@ -81,7 +81,7 @@ Pl_PNGFilter::write(unsigned char* data, size_t len)
81 81 // Swap rows
82 82 unsigned char* t = this->prev_row;
83 83 this->prev_row = this->cur_row;
84   - this->cur_row = t ? t : this->buf2;
  84 + this->cur_row = t ? t : this->buf2.getPointer();
85 85 memset(this->cur_row, 0, this->bytes_per_row + 1);
86 86 left = this->incoming;
87 87 this->pos = 0;
... ... @@ -269,7 +269,7 @@ Pl_PNGFilter::finish()
269 269 processRow();
270 270 }
271 271 this->prev_row = 0;
272   - this->cur_row = buf1;
  272 + this->cur_row = buf1.getPointer();
273 273 this->pos = 0;
274 274 memset(this->cur_row, 0, this->bytes_per_row + 1);
275 275  
... ...
libqpdf/Pl_RC4.cc
... ... @@ -8,19 +8,18 @@ Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next,
8 8 out_bufsize(out_bufsize),
9 9 rc4(key_data, key_len)
10 10 {
11   - this->outbuf = new unsigned char[out_bufsize];
  11 + this->outbuf = PointerHolder<unsigned char>(
  12 + true, new unsigned char[out_bufsize]);
12 13 }
13 14  
14 15 Pl_RC4::~Pl_RC4()
15 16 {
16   - delete [] this->outbuf;
17   - this->outbuf = 0;
18 17 }
19 18  
20 19 void
21 20 Pl_RC4::write(unsigned char* data, size_t len)
22 21 {
23   - if (this->outbuf == 0)
  22 + if (this->outbuf.getPointer() == 0)
24 23 {
25 24 throw std::logic_error(
26 25 this->identifier +
... ... @@ -35,16 +34,15 @@ Pl_RC4::write(unsigned char* data, size_t len)
35 34 size_t bytes =
36 35 (bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
37 36 bytes_left -= bytes;
38   - rc4.process(p, bytes, outbuf);
  37 + rc4.process(p, bytes, outbuf.getPointer());
39 38 p += bytes;
40   - getNext()->write(outbuf, bytes);
  39 + getNext()->write(outbuf.getPointer(), bytes);
41 40 }
42 41 }
43 42  
44 43 void
45 44 Pl_RC4::finish()
46 45 {
47   - delete [] this->outbuf;
48 46 this->outbuf = 0;
49 47 this->getNext()->finish();
50 48 }
... ...
libqpdf/Pl_TIFFPredictor.cc
... ... @@ -16,7 +16,6 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(char const* identifier, Pipeline* next,
16 16 columns(columns),
17 17 samples_per_pixel(samples_per_pixel),
18 18 bits_per_sample(bits_per_sample),
19   - cur_row(0),
20 19 pos(0)
21 20 {
22 21 if (samples_per_pixel < 1)
... ... @@ -38,13 +37,13 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(char const* identifier, Pipeline* next,
38 37 "TIFFPredictor created with invalid columns value");
39 38 }
40 39 this->bytes_per_row = bpr & UINT_MAX;
41   - this->cur_row = new unsigned char[this->bytes_per_row];
42   - memset(this->cur_row, 0, this->bytes_per_row);
  40 + this->cur_row = PointerHolder<unsigned char>(
  41 + true, new unsigned char[this->bytes_per_row]);
  42 + memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
43 43 }
44 44  
45 45 Pl_TIFFPredictor::~Pl_TIFFPredictor()
46 46 {
47   - delete [] cur_row;
48 47 }
49 48  
50 49 void
... ... @@ -55,20 +54,20 @@ Pl_TIFFPredictor::write(unsigned char* data, size_t len)
55 54 while (len >= left)
56 55 {
57 56 // finish off current row
58   - memcpy(this->cur_row + this->pos, data + offset, left);
  57 + memcpy(this->cur_row.getPointer() + this->pos, data + offset, left);
59 58 offset += left;
60 59 len -= left;
61 60  
62 61 processRow();
63 62  
64 63 // Prepare for next row
65   - memset(this->cur_row, 0, this->bytes_per_row);
  64 + memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
66 65 left = this->bytes_per_row;
67 66 this->pos = 0;
68 67 }
69 68 if (len)
70 69 {
71   - memcpy(this->cur_row + this->pos, data + offset, len);
  70 + memcpy(this->cur_row.getPointer() + this->pos, data + offset, len);
72 71 }
73 72 this->pos += len;
74 73 }
... ... @@ -79,7 +78,7 @@ Pl_TIFFPredictor::processRow()
79 78 QTC::TC("libtests", "Pl_TIFFPredictor processRow",
80 79 (action == a_decode ? 0 : 1));
81 80 BitWriter bw(this->getNext());
82   - BitStream in(this->cur_row, this->bytes_per_row);
  81 + BitStream in(this->cur_row.getPointer(), this->bytes_per_row);
83 82 std::vector<long long> prev;
84 83 for (unsigned int i = 0; i < this->samples_per_pixel; ++i)
85 84 {
... ... @@ -118,6 +117,6 @@ Pl_TIFFPredictor::finish()
118 117 processRow();
119 118 }
120 119 this->pos = 0;
121   - memset(this->cur_row, 0, this->bytes_per_row);
  120 + memset(this->cur_row.getPointer(), 0, this->bytes_per_row);
122 121 getNext()->finish();
123 122 }
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1835,21 +1835,21 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
1835 1835 this->m->cur_data_key.length());
1836 1836 pl.write(QUtil::unsigned_char_pointer(val), val.length());
1837 1837 pl.finish();
1838   - Buffer* buf = bufpl.getBuffer();
  1838 + PointerHolder<Buffer> buf = bufpl.getBuffer();
1839 1839 val = QPDF_String(
1840 1840 std::string(reinterpret_cast<char*>(buf->getBuffer()),
1841 1841 buf->getSize())).unparse(true);
1842   - delete buf;
1843 1842 }
1844 1843 else
1845 1844 {
1846   - char* tmp = QUtil::copy_string(val);
  1845 + PointerHolder<char> tmp_ph =
  1846 + PointerHolder<char>(true, QUtil::copy_string(val));
  1847 + char* tmp = tmp_ph.getPointer();
1847 1848 size_t vlen = val.length();
1848 1849 RC4 rc4(QUtil::unsigned_char_pointer(this->m->cur_data_key),
1849 1850 QIntC::to_int(this->m->cur_data_key.length()));
1850 1851 rc4.process(QUtil::unsigned_char_pointer(tmp), vlen);
1851 1852 val = QPDF_String(std::string(tmp, vlen)).unparse();
1852   - delete [] tmp;
1853 1853 }
1854 1854 }
1855 1855 else
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -204,7 +204,9 @@ iterate_rc4(unsigned char* data, size_t data_len,
204 204 unsigned char* okey, int key_len,
205 205 int iterations, bool reverse)
206 206 {
207   - unsigned char* key = new unsigned char[QIntC::to_size(key_len)];
  207 + PointerHolder<unsigned char> key_ph = PointerHolder<unsigned char>(
  208 + true, new unsigned char[QIntC::to_size(key_len)]);
  209 + unsigned char* key = key_ph.getPointer();
208 210 for (int i = 0; i < iterations; ++i)
209 211 {
210 212 int const xor_value = (reverse ? iterations - 1 - i : i);
... ... @@ -215,7 +217,6 @@ iterate_rc4(unsigned char* data, size_t data_len,
215 217 RC4 rc4(key, QIntC::to_int(key_len));
216 218 rc4.process(data, data_len);
217 219 }
218   - delete [] key;
219 220 }
220 221  
221 222 static std::string
... ...
libqpdf/QUtil.cc
... ... @@ -670,10 +670,9 @@ QUtil::get_env(std::string const&amp; var, std::string* value)
670 670  
671 671 if (value)
672 672 {
673   - char* t = new char[len + 1];
674   - ::GetEnvironmentVariable(var.c_str(), t, len);
675   - *value = t;
676   - delete [] t;
  673 + PointerHolder<char> t = PointerHolder<char>(true, new char[len + 1]);
  674 + ::GetEnvironmentVariable(var.c_str(), t.getPointer(), len);
  675 + *value = t.getPointer();
677 676 }
678 677  
679 678 return true;
... ...
libqpdf/qpdf-c.cc
... ... @@ -22,8 +22,8 @@ struct _qpdf_data
22 22 _qpdf_data();
23 23 ~_qpdf_data();
24 24  
25   - QPDF* qpdf;
26   - QPDFWriter* qpdf_writer;
  25 + PointerHolder<QPDF> qpdf;
  26 + PointerHolder<QPDFWriter> qpdf_writer;
27 27  
28 28 PointerHolder<QPDFExc> error;
29 29 _qpdf_error tmp_error;
... ... @@ -36,22 +36,16 @@ struct _qpdf_data
36 36 unsigned long long size;
37 37 char const* password;
38 38 bool write_memory;
39   - Buffer* output_buffer;
  39 + PointerHolder<Buffer> output_buffer;
40 40 };
41 41  
42 42 _qpdf_data::_qpdf_data() :
43   - qpdf(0),
44   - qpdf_writer(0),
45   - write_memory(false),
46   - output_buffer(0)
  43 + write_memory(false)
47 44 {
48 45 }
49 46  
50 47 _qpdf_data::~_qpdf_data()
51 48 {
52   - delete qpdf_writer;
53   - delete qpdf;
54   - delete output_buffer;
55 49 }
56 50  
57 51 // must set qpdf->filename and qpdf->password
... ... @@ -451,14 +445,12 @@ QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf)
451 445  
452 446 static void qpdf_init_write_internal(qpdf_data qpdf)
453 447 {
454   - if (qpdf->qpdf_writer)
  448 + if (qpdf->qpdf_writer.getPointer())
455 449 {
456 450 QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times");
457   - delete qpdf->qpdf_writer;
458 451 qpdf->qpdf_writer = 0;
459   - if (qpdf->output_buffer)
  452 + if (qpdf->output_buffer.getPointer())
460 453 {
461   - delete qpdf->output_buffer;
462 454 qpdf->output_buffer = 0;
463 455 qpdf->write_memory = false;
464 456 qpdf->filename = 0;
... ... @@ -496,7 +488,7 @@ size_t qpdf_get_buffer_length(qpdf_data qpdf)
496 488 {
497 489 qpdf_get_buffer_internal(qpdf);
498 490 size_t result = 0;
499   - if (qpdf->output_buffer)
  491 + if (qpdf->output_buffer.getPointer())
500 492 {
501 493 result = qpdf->output_buffer->getSize();
502 494 }
... ... @@ -507,7 +499,7 @@ unsigned char const* qpdf_get_buffer(qpdf_data qpdf)
507 499 {
508 500 unsigned char const* result = 0;
509 501 qpdf_get_buffer_internal(qpdf);
510   - if (qpdf->output_buffer)
  502 + if (qpdf->output_buffer.getPointer())
511 503 {
512 504 result = qpdf->output_buffer->getBuffer();
513 505 }
... ...
libqpdf/qpdf/Pl_AES_PDF.hh
... ... @@ -55,8 +55,8 @@ class Pl_AES_PDF: public Pipeline
55 55 bool cbc_mode;
56 56 bool first;
57 57 size_t offset; // offset into memory buffer
58   - unsigned char* key;
59   - uint32_t* rk;
  58 + PointerHolder<unsigned char> key;
  59 + PointerHolder<uint32_t> rk;
60 60 unsigned char inbuf[buf_size];
61 61 unsigned char outbuf[buf_size];
62 62 unsigned char cbc_block[buf_size];
... ...
libqpdf/qpdf/Pl_PNGFilter.hh
... ... @@ -41,10 +41,10 @@ class Pl_PNGFilter: public Pipeline
41 41 action_e action;
42 42 unsigned int bytes_per_row;
43 43 unsigned int bytes_per_pixel;
44   - unsigned char* cur_row;
45   - unsigned char* prev_row;
46   - unsigned char* buf1;
47   - unsigned char* buf2;
  44 + unsigned char* cur_row; // points to buf1 or buf2
  45 + unsigned char* prev_row; // points to buf1 or buf2
  46 + PointerHolder<unsigned char> buf1;
  47 + PointerHolder<unsigned char> buf2;
48 48 size_t pos;
49 49 size_t incoming;
50 50 };
... ...
libqpdf/qpdf/Pl_RC4.hh
... ... @@ -24,7 +24,7 @@ class Pl_RC4: public Pipeline
24 24 virtual void finish();
25 25  
26 26 private:
27   - unsigned char* outbuf;
  27 + PointerHolder<unsigned char> outbuf;
28 28 size_t out_bufsize;
29 29 RC4 rc4;
30 30 };
... ...
libqpdf/qpdf/Pl_TIFFPredictor.hh
... ... @@ -32,7 +32,7 @@ class Pl_TIFFPredictor: public Pipeline
32 32 unsigned int bytes_per_row;
33 33 unsigned int samples_per_pixel;
34 34 unsigned int bits_per_sample;
35   - unsigned char* cur_row;
  35 + PointerHolder<unsigned char> cur_row;
36 36 size_t pos;
37 37 };
38 38  
... ...
zlib-flate/zlib-flate.cc
... ... @@ -61,8 +61,9 @@ int main(int argc, char* argv[])
61 61  
62 62 QUtil::binary_stdout();
63 63 QUtil::binary_stdin();
64   - Pl_StdioFile* out = new Pl_StdioFile("stdout", stdout);
65   - Pl_Flate* flate = new Pl_Flate("flate", out, action);
  64 + PointerHolder<Pl_StdioFile> out = new Pl_StdioFile("stdout", stdout);
  65 + PointerHolder<Pl_Flate> flate =
  66 + new Pl_Flate("flate", out.getPointer(), action);
66 67  
67 68 try
68 69 {
... ... @@ -81,8 +82,6 @@ int main(int argc, char* argv[])
81 82 }
82 83 }
83 84 flate->finish();
84   - delete flate;
85   - delete out;
86 85 }
87 86 catch (std::exception& e)
88 87 {
... ...