From 76c04a4a5d2273f9728042fca2f6657de49c03e7 Mon Sep 17 00:00:00 2001 From: Chris Gunther Date: Sun, 12 Mar 2017 21:04:35 -0400 Subject: [PATCH] WIP: Avoid stack overflow when decrypting objects --- lib/pdf/reader/object_hash.rb | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/pdf/reader/object_hash.rb b/lib/pdf/reader/object_hash.rb index e08c4879..652a650a 100644 --- a/lib/pdf/reader/object_hash.rb +++ b/lib/pdf/reader/object_hash.rb @@ -81,7 +81,7 @@ def [](key) @cache[key] elsif xref[key].is_a?(Integer) buf = new_buffer(xref[key]) - @cache[key] = decrypt(key, Parser.new(buf, self).object(key.id, key.gen)) + @cache[key] = decrypt(key, Parser.new(buf, self).object(key.id, key.gen), {}) elsif xref[key].is_a?(PDF::Reader::Reference) container_key = xref[key] object_streams[container_key] ||= PDF::Reader::ObjectStream.new(object(container_key)) @@ -308,16 +308,27 @@ def build_security_handler(opts = {}) end end - def decrypt(ref, obj) + def decrypt(ref, obj, seen) + seen_key = obj.object_id + + return seen[seen_key] if seen.key?(seen_key) + case obj when PDF::Reader::Stream then obj.data = sec_handler.decrypt(obj.data, ref) obj when Hash then - arr = obj.map { |key,val| [key, decrypt(ref, val)] }.flatten(1) - Hash[*arr] + seen[seen_key] ||= {} + obj.each do |key,val| + seen[seen_key][key] = decrypt(ref, val, seen) + end + seen[seen_key] when Array then - obj.collect { |item| decrypt(ref, item) } + seen[seen_key] ||= [] + obj.each do |item| + seen[seen_key] << decrypt(ref, item, seen) + end + seen[seen_key] when String sec_handler.decrypt(obj, ref) else