diff options
author | Jay Berkenbilt <ejb@ql.org> | 2019-08-28 04:10:11 +0200 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2019-08-28 04:27:47 +0200 |
commit | ba5fb6916446d8bdf79cba25f08d759bc5595aec (patch) | |
tree | da6691079e5feacc571127cc062482df9ba4399c /include | |
parent | dadf8307c83706c3b097bc4b1fe7b24defbebb8e (diff) | |
download | qpdf-ba5fb6916446d8bdf79cba25f08d759bc5595aec.tar.zst |
Make popping pipeline stack safer
Use destructors to pop the pipeline stack, and ensure that code that
pops the stack is actually popping the intended thing.
Diffstat (limited to 'include')
-rw-r--r-- | include/qpdf/Pipeline.hh | 2 | ||||
-rw-r--r-- | include/qpdf/QPDFWriter.hh | 50 |
2 files changed, 38 insertions, 14 deletions
diff --git a/include/qpdf/Pipeline.hh b/include/qpdf/Pipeline.hh index 36a25df0..e8f62b4e 100644 --- a/include/qpdf/Pipeline.hh +++ b/include/qpdf/Pipeline.hh @@ -70,6 +70,8 @@ class QPDF_DLL_CLASS Pipeline virtual void write(unsigned char* data, size_t len) = 0; QPDF_DLL virtual void finish() = 0; + QPDF_DLL + std::string getIdentifier() const; protected: Pipeline* getNext(bool allow_null = false); diff --git a/include/qpdf/QPDFWriter.hh b/include/qpdf/QPDFWriter.hh index 0fd114db..c3818ae4 100644 --- a/include/qpdf/QPDFWriter.hh +++ b/include/qpdf/QPDFWriter.hh @@ -473,6 +473,34 @@ class QPDFWriter enum trailer_e { t_normal, t_lin_first, t_lin_second }; + // An reference to a PipelinePopper instance is passed into + // activatePipelineStack. When the PipelinePopper goes out of + // scope, the pipeline stack is popped. PipelinePopper's + // destructor calls finish on the current pipeline and pops the + // pipeline stack until the top of stack is a previous active top + // of stack, and restores the pipeline to that point. It deletes + // any pipelines that it pops. If the bp argument is non-null and + // any of the stack items are of type Pl_Buffer, the buffer is + // retrieved. + class PipelinePopper + { + friend class QPDFWriter; + public: + PipelinePopper(QPDFWriter* qw, + PointerHolder<Buffer>* bp = 0) : + qw(qw), + bp(bp) + { + } + ~PipelinePopper(); + + private: + QPDFWriter* qw; + PointerHolder<Buffer>* bp; + std::string stack_id; + }; + friend class PipelinePopper; + unsigned int bytesNeeded(long long n); void writeBinary(unsigned long long val, unsigned int bytes); void writeString(std::string const& str); @@ -560,24 +588,17 @@ class QPDFWriter int calculateXrefStreamPadding(qpdf_offset_t xref_bytes); // When filtering subsections, push additional pipelines to the - // stack. When ready to switch, activate the pipeline stack. - // Pipelines passed to pushPipeline are deleted when - // clearPipelineStack is called. + // stack. When ready to switch, activate the pipeline stack. When + // the passed in PipelinePopper goes out of scope, the stack is + // popped. Pipeline* pushPipeline(Pipeline*); - void activatePipelineStack(); + void activatePipelineStack(PipelinePopper&); void initializePipelineStack(Pipeline *); - // Calls finish on the current pipeline and pops the pipeline - // stack until the top of stack is a previous active top of stack, - // and restores the pipeline to that point. Deletes any pipelines - // that it pops. If the bp argument is non-null and any of the - // stack items are of type Pl_Buffer, the buffer is retrieved. - void popPipelineStack(PointerHolder<Buffer>* bp = 0); - void adjustAESStreamLength(size_t& length); - void pushEncryptionFilter(); - void pushDiscardFilter(); - void pushMD5Pipeline(); + void pushEncryptionFilter(PipelinePopper&); + void pushDiscardFilter(PipelinePopper&); + void pushMD5Pipeline(PipelinePopper&); void computeDeterministicIDData(); void discardGeneration(std::map<QPDFObjGen, int> const& in, @@ -654,6 +675,7 @@ class QPDFWriter std::map<QPDFObjGen, int> object_to_object_stream; std::map<int, std::set<QPDFObjGen> > object_stream_to_objects; std::list<Pipeline*> pipeline_stack; + unsigned long long next_stack_id; bool deterministic_id; Pl_MD5* md5_pipeline; std::string deterministic_id_data; |