Skip to content

Commit

Permalink
stream.rb: get the partially decoded data when an error occurs during…
Browse files Browse the repository at this point in the history
… decoding
  • Loading branch information
darko committed Oct 21, 2011
1 parent da81192 commit f2064f5
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 37 deletions.
2 changes: 1 addition & 1 deletion Rakefile.rb
Expand Up @@ -7,7 +7,7 @@

spec = Gem::Specification.new do |s|
s.name = "origami"
s.version = "1.2.2"
s.version = "1.2.4"
s.author = "Guillaume Delugré"
s.email = "guillaume at security-labs dot org"
s.homepage = "http://aslr.fr/pages/Origami"
Expand Down
10 changes: 10 additions & 0 deletions lib/origami/filters.rb
Expand Up @@ -30,6 +30,16 @@ module Origami
#
module Filter

class InvalidFilterDataError < Exception # :nodoc:
attr_reader :decoded_data

def initialize(message, decoded_data = nil)
super(message)

@decoded_data = decoded_data
end
end

module Utils

class BitWriterError < Exception #:nodoc:
Expand Down
19 changes: 12 additions & 7 deletions lib/origami/filters/ascii.rb
Expand Up @@ -27,7 +27,7 @@ module Origami

module Filter

class InvalidASCIIHexStringError < Exception #:nodoc:
class InvalidASCIIHexStringError < InvalidFilterDataError #:nodoc:
end

#
Expand Down Expand Up @@ -64,7 +64,7 @@ def decode(string)

end

class InvalidASCII85StringError < Exception #:nodoc:
class InvalidASCII85StringError < InvalidFilterDataError #:nodoc:
end

#
Expand Down Expand Up @@ -141,7 +141,7 @@ def decode(string)
codelen = 5

if input.length - i < 5
raise InvalidASCII85StringError, "Invalid length" if input.length - i == 1
raise InvalidASCII85StringError.new("Invalid length", result) if input.length - i == 1

addend = 5 - (input.length - i)
input << "u" * addend
Expand All @@ -152,15 +152,20 @@ def decode(string)
# Checking if this string is in base85
5.times do |j|
if input[i+j].ord > "u"[0].ord or input[i+j].ord < "!"[0].ord
raise InvalidASCII85StringError, "Invalid character sequence: #{input[i,5].inspect}"
raise InvalidASCII85StringError.new(
"Invalid character sequence: #{input[i,5].inspect}",
result
)
else
inblock += (input[i+j].ord - "!"[0].ord) * 85 ** (4 - j)
end
end

if inblock >= 2**32
raise InvalidASCII85StringError, "Invalid value (#{inblock}) for block #{input[i,5].inspect}"
end

raise InvalidASCII85StringError.new(
"Invalid value (#{inblock}) for block #{input[i,5].inspect}",
result
) if inblock >= 2**32

end

Expand Down
17 changes: 13 additions & 4 deletions lib/origami/filters/ccitt.rb
Expand Up @@ -27,7 +27,7 @@ module Origami

module Filter

class InvalidCCITTFaxDataError < Exception #:nodoc:
class InvalidCCITTFaxDataError < InvalidFilterDataError #:nodoc:
end

class CCITTFaxFilterError < Exception #:nodoc:
Expand Down Expand Up @@ -404,7 +404,10 @@ def decode(stream)

# checking for the presence of EOL
if bitr.peek(EOL[1]) != EOL[0]
raise CCITTFaxFilterError, "No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})" if has_eol
raise InvalidCCITTFaxDataError.new(
"No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
bitw.final.to_s
)if has_eol
else
bitr.pos += EOL[1]
end
Expand All @@ -417,10 +420,16 @@ def decode(stream)
bit_length = get_black_bits(bitr)
end

raise CCITTFaxFilterError, "Unfinished line (at bit pos #{bitr.pos}/#{bitr.size}})" if bit_length.nil?
raise InvalidCCITTFaxDataError.new(
"Unfinished line (at bit pos #{bitr.pos}/#{bitr.size}})",
bitw.final.to_s
) if bit_length.nil?

line_length += bit_length
raise CCITTFaxFilterError, "Line is too long (at bit pos #{bitr.pos}/#{bitr.size}})" if line_length > columns
raise InvalidCCITTFaxDataError.new(
"Line is too long (at bit pos #{bitr.pos}/#{bitr.size}})",
bitw.final.to_s
) if line_length > columns

write_bit_range(bitw, current_color, bit_length)
current_color ^= 1
Expand Down
13 changes: 2 additions & 11 deletions lib/origami/filters/flate.rb
Expand Up @@ -30,16 +30,7 @@ module Origami

module Filter

class InvalidFlateDataError < Exception #:nodoc:
attr_reader :zlib_stream, :zlib_except

def initialize(zlib_stream, zlib_except)
super(zlib_except.message)

@zlib_stream = zlib_stream
@zlib_except = zlib_except
end
end
class InvalidFlateDataError < InvalidFilterDataError; end #:nodoc:

#
# Class representing a Filter used to encode and decode data with zlib/Flate compression algorithm.
Expand Down Expand Up @@ -92,7 +83,7 @@ def decode(stream)
begin
uncompressed = zlib_stream.inflate(stream)
rescue Zlib::DataError => zlib_except
raise InvalidFlateDataError.new(zlib_stream, zlib_except)
raise InvalidFlateDataError.new(zlibexcept.message, zlib_stream.flush_next_out)
end

if @params.Predictor.is_a?(Integer)
Expand Down
13 changes: 10 additions & 3 deletions lib/origami/filters/lzw.rb
Expand Up @@ -29,7 +29,7 @@ module Origami

module Filter

class InvalidLZWDataError < Exception #:nodoc:
class InvalidLZWDataError < InvalidFilterDataError #:nodoc:
end

#
Expand Down Expand Up @@ -131,8 +131,10 @@ def decode(string)
when 4095
if byte != CLEARTABLE
then
raise InvalidLZWDataError,
"LZW table is full and no clear flag was set (codeword #{byte.to_s(2).rjust(codesize,'0')} at bit #{bstring.pos - codesize}/#{bstring.size})"
raise InvalidLZWDataError.new(
"LZW table is full and no clear flag was set (codeword #{byte.to_s(2).rjust(codesize,'0')} at bit #{bstring.pos - codesize}/#{bstring.size})",
result
)
end
end

Expand All @@ -150,6 +152,11 @@ def decode(string)
result << table.key(byte)
redo
else
raise InvalidLZWDataError.new(
"No entry for codeword #{prevbyte.to_s(2).rjust(codesize,'0')}.",
result
) unless table.key(prevbyte)

if table.has_value?(byte)
entry = table.key(byte)
else
Expand Down
2 changes: 1 addition & 1 deletion lib/origami/filters/runlength.rb
Expand Up @@ -27,7 +27,7 @@ module Origami

module Filter

class InvalidRunLengthDataError < Exception #:nodoc:
class InvalidRunLengthDataError < InvalidFilterDataError #:nodoc:
end

#
Expand Down
2 changes: 1 addition & 1 deletion lib/origami/pdf.rb
Expand Up @@ -61,7 +61,7 @@

module Origami

VERSION = "1.2.3"
VERSION = "1.2.4"
REVISION = "$Revision$" #:nodoc:

#
Expand Down
19 changes: 10 additions & 9 deletions lib/origami/stream.rb
Expand Up @@ -249,11 +249,19 @@ def decode!
filters = [ filters ] unless filters.is_a?(::Array)

@data = @rawdata.dup
@data.freeze

filters.length.times do |layer|
params = dparams[layer].is_a?(Dictionary) ? dparams[layer] : {}
filter = filters[layer]

@data = decode_data(@data, filter, params)
begin
@data = decode_data(@data, filter, params)
rescue Filter::InvalidFilterDataError => e
@data = e.decoded_data if e.decoded_data
raise InvalidStreamObjectError,
"Error while decoding stream #{self.reference}\n\t-> [#{e.class}] #{e.message}"
end
end
else
raise InvalidStreamObjectError, "Invalid Filter type parameter"
Expand Down Expand Up @@ -357,15 +365,8 @@ def decode_data(data, filter, params) #:nodoc:
raise InvalidStreamObjectError, "Unknown filter : #{filter}"
end

begin
Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).decode(data, params)

rescue Filter::InvalidFlateDataError => flate_e
return flate_e.zlib_stream.flush_next_out
Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).decode(data, params)

rescue Exception => e
raise InvalidStreamObjectError, "Error while decoding stream #{self.reference}\n\t-> [#{e.class}] #{e.message}"
end
end

def encode_data(data, filter, params) #:nodoc:
Expand Down

0 comments on commit f2064f5

Please sign in to comment.