yob / pdf-reader

The PDF::Reader library implements a PDF parser conforming as much as possible to the PDF specification from Adobe.
MIT License
1.81k stars 271 forks source link

Validate callbacks when extracting text from a form xobject #462

Closed yob closed 2 years ago

yob commented 2 years ago

This mirrors the change made in #437 for standard page content that's not in a form xobject.

The commit message there is also relevant here:

Page#walk will execute the content stream of a page, calling methods on a receiver class provided by the user. Each operator has a specific set of parameters it expects, and we wrap the users receiver class in this one to verify the PDF uses valid parameters.

Without these checks, users can't be confident about the number of parameters they'll receive for an operator, or what the type of those parameters will be. Everyone ends up building their own type safety guard clauses and it's tedious.

Not all operators have type safety implemented yet, but we can expand the number over time.

This fixes a large number of potential crashes exposed by the fuzzer added in #429. When it flips bits in some content streams the parameters that are passed to receivers can change in number of type, raising exceptions we don't want to raise (like NoMethodError).

yob commented 2 years ago

@bcoles this should make a big improvement to the number of unique crashes the fuzzer finds

bcoles commented 2 years ago

@bcoles this should make a big improvement to the number of unique crashes the fuzzer finds

The number of unique crash locations remains about the same.

$ head -n 2 crashes/*.trace | grep ":in " | sort -u | wc -l
64

Directories 1 through 4 are older runs. While the number of crashes decreased (sort of) the total number of crashes isn't a reliable metric as the fuzzer is not deterministic and two of those runs were terminated by an OOM bug (3 and 4 iirc).

user@ubuntu:~/Desktop/pdf-reader$ ls -la crashes.1/*.trace | wc -l
2596
user@ubuntu:~/Desktop/pdf-reader$ ls -la crashes.2/*.trace | wc -l
3062
user@ubuntu:~/Desktop/pdf-reader$ ls -la crashes.3/*.trace | wc -l
1406
user@ubuntu:~/Desktop/pdf-reader$ ls -la crashes.4/*.trace | wc -l
1308
user@ubuntu:~/Desktop/pdf-reader$ ls -la crashes/*.trace | wc -l
1262

The number of unique crash messages didn't change much either.

``` $ head -n 1 crashes/*.trace | fgrep -v "==>" | sort -u 131..131 out of range bad decrypt can't iterate from Float comparison of String with 3 failed diff (0) must be a Array execution expired Invalid filter algorithm 10 Invalid filter algorithm 101 Invalid filter algorithm 102 Invalid filter algorithm 106 Invalid filter algorithm 108 Invalid filter algorithm 109 Invalid filter algorithm 11 Invalid filter algorithm 116 Invalid filter algorithm 118 Invalid filter algorithm 119 Invalid filter algorithm 12 Invalid filter algorithm 121 Invalid filter algorithm 124 Invalid filter algorithm 126 Invalid filter algorithm 127 Invalid filter algorithm 129 Invalid filter algorithm 13 Invalid filter algorithm 130 Invalid filter algorithm 134 Invalid filter algorithm 138 Invalid filter algorithm 140 Invalid filter algorithm 143 Invalid filter algorithm 145 Invalid filter algorithm 148 Invalid filter algorithm 149 Invalid filter algorithm 15 Invalid filter algorithm 151 Invalid filter algorithm 154 Invalid filter algorithm 158 Invalid filter algorithm 16 Invalid filter algorithm 160 Invalid filter algorithm 162 Invalid filter algorithm 164 Invalid filter algorithm 168 Invalid filter algorithm 17 Invalid filter algorithm 173 Invalid filter algorithm 175 Invalid filter algorithm 178 Invalid filter algorithm 18 Invalid filter algorithm 180 Invalid filter algorithm 181 Invalid filter algorithm 182 Invalid filter algorithm 183 Invalid filter algorithm 184 Invalid filter algorithm 186 Invalid filter algorithm 19 Invalid filter algorithm 190 Invalid filter algorithm 193 Invalid filter algorithm 196 Invalid filter algorithm 20 Invalid filter algorithm 202 Invalid filter algorithm 205 Invalid filter algorithm 207 Invalid filter algorithm 211 Invalid filter algorithm 212 Invalid filter algorithm 214 Invalid filter algorithm 215 Invalid filter algorithm 219 Invalid filter algorithm 22 Invalid filter algorithm 222 Invalid filter algorithm 224 Invalid filter algorithm 23 Invalid filter algorithm 230 Invalid filter algorithm 231 Invalid filter algorithm 234 Invalid filter algorithm 235 Invalid filter algorithm 238 Invalid filter algorithm 239 Invalid filter algorithm 24 Invalid filter algorithm 240 Invalid filter algorithm 241 Invalid filter algorithm 242 Invalid filter algorithm 243 Invalid filter algorithm 245 Invalid filter algorithm 246 Invalid filter algorithm 25 Invalid filter algorithm 250 Invalid filter algorithm 252 Invalid filter algorithm 253 Invalid filter algorithm 254 Invalid filter algorithm 255 Invalid filter algorithm 26 Invalid filter algorithm 27 Invalid filter algorithm 28 Invalid filter algorithm 31 Invalid filter algorithm 32 Invalid filter algorithm 34 Invalid filter algorithm 35 Invalid filter algorithm 38 Invalid filter algorithm 40 Invalid filter algorithm 42 Invalid filter algorithm 44 Invalid filter algorithm 45 Invalid filter algorithm 46 Invalid filter algorithm 47 Invalid filter algorithm 48 Invalid filter algorithm 49 Invalid filter algorithm 5 Invalid filter algorithm 50 Invalid filter algorithm 51 Invalid filter algorithm 52 Invalid filter algorithm 53 Invalid filter algorithm 54 Invalid filter algorithm 55 Invalid filter algorithm 56 Invalid filter algorithm 57 Invalid filter algorithm 58 Invalid filter algorithm 59 Invalid filter algorithm 6 Invalid filter algorithm 60 Invalid filter algorithm 64 Invalid filter algorithm 66 Invalid filter algorithm 67 Invalid filter algorithm 69 Invalid filter algorithm 7 Invalid filter algorithm 70 Invalid filter algorithm 71 Invalid filter algorithm 72 Invalid filter algorithm 73 Invalid filter algorithm 74 Invalid filter algorithm 75 Invalid filter algorithm 76 Invalid filter algorithm 79 Invalid filter algorithm 8 Invalid filter algorithm 80 Invalid filter algorithm 81 Invalid filter algorithm 82 Invalid filter algorithm 83 Invalid filter algorithm 84 Invalid filter algorithm 85 Invalid filter algorithm 87 Invalid filter algorithm 89 Invalid filter algorithm 90 Invalid filter algorithm 92 Invalid filter algorithm 93 Invalid filter algorithm 95 Invalid filter algorithm 96 Invalid filter algorithm 97 Invalid filter algorithm 98 iv must be 16 bytes NaN nil can't be coerced into Float nil can't be coerced into Integer no implicit conversion from nil to integer no implicit conversion of Hash into Integer no implicit conversion of Integer into String no implicit conversion of nil into String no implicit conversion of Symbol into Integer stack level too deep undefined method `a' for nil:NilClass undefined method `fetch' for 0:Integer undefined method `fetch' for 9:Integer undefined method `fetch' for "":String undefined method `fetch' for "\x00":String undefined method `fetch' for "\x90":String undefined method `+' for nil:NilClass undefined method `-' for nil:NilClass undefined method `[]' for nil:NilClass undefined method `[]=' for nil:NilClass undefined method `-' for # undefined method `-' for "\x13":String undefined method `gsub' for # undefined method `gsub' for # undefined method `gsub' for # undefined method `gsub' for # undefined method `gsub' for # undefined method `gsub' for # undefined method `pack' for nil:NilClass undefined method `times' for nil:NilClass undefined method `times' for ")":PDF::Reader::Token undefined method `to_i' for [444, 500, 444, 500, 444, 333]:Array undefined method `to_i' for [615, 552, 781, 719, 281, 500, 667, 552, 833]:Array undefined method `to_i' for [666, 610, 777, 722, 277, 500, 666, 556, 833, 722, 777, 666]:Array undefined method `to_i' for [666, 610]:Array undefined method `unfiltered_data' for 0:Integer undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for # undefined method `unfiltered_data' for nil:NilClass undefined method `unfiltered_data' for "":String undefined method `unfiltered_data' for "\x00":String undefined method `unfiltered_data' for "\xD0":String undefined method `unpack' for nil:NilClass wrong number of arguments (given 5, expected 6) ```
yob commented 2 years ago

The number of unique crash locations remains about the same.

Interesting! I based my assumption on the number of page_state.rb errors in the list here: https://github.com/yob/pdf-reader/pull/421#issuecomment-1100890409

Is this the non-determinism at play?

whack-a-mole

bcoles commented 2 years ago

The number of unique crash locations remains about the same.

Interesting! I based my assumption on the number of page_state.rb errors in the list here: #421 (comment)

Is this the non-determinism at play?

There's still a bunch of issues in page_state.rb.

$ head -n 2 crashes.5/*.trace | grep page_state | wc -l
179
$ head -n 2 crashes.5/*.trace | grep page_state | sort -u | wc -l
12
$ head -n 2 crashes.5/*.trace | grep page_state | sort -u
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:107:in `set_text_font_and_size'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:120:in `set_text_leading'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:132:in `set_word_spacing'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:144:in `move_text_position'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:197:in `[]'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:197:in `hash'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:247:in `current_font'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:356:in `*'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:405:in `new'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:66:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:67:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:99:in `set_character_spacing'

Although down slightly from an earlier run:

$ head -n 2 crashes.1/*.trace | grep page_state | wc -l
208
$ head -n 2 crashes.1/*.trace | grep page_state | sort -u | wc -l
19
$ head -n 2 crashes.1/*.trace | grep page_state | sort -u
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:106:in `set_text_font_and_size'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:107:in `set_text_font_and_size'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:120:in `set_text_leading'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:127:in `set_text_rise'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:132:in `set_word_spacing'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:139:in `move_text_position'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:144:in `move_text_position'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:157:in `set_text_matrix_and_text_line_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:197:in `[]'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:197:in `hash'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:247:in `current_font'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:251:in `detect'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:45:in `save_graphics_state'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:51:in `restore_graphics_state'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:66:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:67:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:84:in `begin_text_object'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:90:in `end_text_object'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:99:in `set_character_spacing'

These fuzz runs are all recent:

drwxrwxr-x  2 user user  380928 Apr 17 02:52 crashes.1
drwxrwxr-x  2 user user  450560 Apr 17 05:57 crashes.2
drwxrwxr-x  2 user user  217088 Apr 17 07:24 crashes.3
drwxrwxr-x  2 user user  200704 Apr 17 08:04 crashes.4
drwxrwxr-x  2 user user  188416 Apr 17 16:20 crashes.5
bcoles commented 2 years ago

The last few commits today have decreased the number of crash locations.

$ head -n 2 crashes/*.trace | grep ":in " | sort -u | wc -l
51
$ head -n 2 crashes/*.trace | grep ":in " | sort -u 
<internal:pack>:257:in `unpack'
/var/lib/gems/2.7.0/gems/hashery-2.1.2/lib/hashery/lru_hash.rb:138:in `has_key?'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/aes_v2_security_handler.rb:36:in `iv='
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/aes_v2_security_handler.rb:37:in `final'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:125:in `read'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:190:in `pos'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:203:in `block in prepare_tokens'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:212:in `last'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:213:in `==='
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:370:in `block in prepare_regular_token'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/buffer.rb:84:in `seek'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/encoding.rb:211:in `each'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/error.rb:51:in `validate_type'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/filter/depredict.rb:41:in `*'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/filter/depredict.rb:69:in `*'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/filter/depredict.rb:74:in `slice!'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/font.rb:109:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/font.rb:110:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/font.rb:167:in `extract_base_info'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/key_builder_v5.rb:62:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/key_builder_v5.rb:73:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/lzw.rb:79:in `chr'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/object_cache.rb:98:in `update_stats'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_layout.rb:40:in `round'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:105:in `set_character_spacing'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:113:in `set_text_font_and_size'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:134:in `set_text_rise'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:253:in `current_font'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:411:in `new'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:72:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/page_state.rb:73:in `concatenate_matrix'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/parser.rb:143:in `pdf_name'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/parser.rb:177:in `block in hex_string'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/reference.rb:54:in `kind_of?'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/reference.rb:64:in `hash'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/security_handler_factory.rb:58:in `standard?'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/security_handler_factory.rb:60:in `standard?'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/standard_key_builder.rb:117:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/standard_key_builder.rb:120:in `auth_user_pass'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/standard_key_builder.rb:135:in `make_file_key'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/standard_key_builder.rb:67:in `pad_pass'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:132:in `=='
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:132:in `include?'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:197:in `+'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:197:in `block in load_xref_stream'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:200:in `[]'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:201:in `[]'
/var/lib/gems/2.7.0/gems/pdf-reader-2.9.2/lib/pdf/reader/xref.rb:202:in `[]'
/var/lib/gems/2.7.0/gems/ruby-rc4-0.1.5/lib/rc4.rb:33:in `process'
/var/lib/gems/2.7.0/gems/ttfunk-1.7.0/lib/ttfunk/directory.rb:18:in `block in initialize'
/var/lib/gems/2.7.0/gems/ttfunk-1.7.0/lib/ttfunk/reader.rb:12:in `read'
$ head -n 1 crashes/*.trace | fgrep -v "==>" | sort -u 

-1 out of char range
:"3" can't be coerced into Integer
bad decrypt
diff (0) must be a Array
execution expired
Invalid argument
iv must be 16 bytes
NaN
negative length -26 given
negative length -5 given
nil can't be coerced into Float
nil can't be coerced into Integer
no implicit conversion from nil to integer
no implicit conversion of Integer into String
no implicit conversion of nil into String
no implicit conversion of PDF::Reader::Token into Integer
no implicit conversion of Symbol into Integer
no implicit conversion of Symbol into String
PDF::Reader::Token can't be coerced into Integer
stack level too deep
undefined method `fetch' for 0:Integer
undefined method `fetch' for 4:Integer
undefined method `fetch' for "":String
undefined method `fetch' for "\x00":String
undefined method `fetch' for "\xD0":String
undefined method `-' for nil:NilClass
undefined method `[]' for nil:NilClass
undefined method `[]=' for nil:NilClass
undefined method `gsub' for nil:NilClass
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d136c80 @id=8, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d3f4828 @id=3, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d4641a0 @id=42, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d4af718 @id=8, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d4b0208 @id=51, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d4cc408 @id=2, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d5b4f78 @id=4, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d627b40 @id=7, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d6c77d0 @id=27, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d7f4040 @id=3, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1d8fccf8 @id=0, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1e178800 @id=22, @gen=0>
undefined method `gsub' for #<PDF::Reader::Reference:0x000055ec1e9f5eb0 @id=12, @gen=0>
undefined method `pack' for nil:NilClass
undefined method `to_i' for [222, 500, 222, 833, 556]:Array
undefined method `to_i' for [333, 500, 281, 552, 500, 719]:Array
undefined method `to_i' for [435]:Array
undefined method `to_i' for [500]:Array
undefined method `to_i' for [525]:Array
undefined method `to_i' for :"5492":Symbol
undefined method `to_i' for [580, 471, 898]:Array
undefined method `unpack' for nil:NilClass
wrong number of arguments (given 5, expected 6)