From 5a8b3c5fcd15b9842cf3f966d7006f1347b98db4 Mon Sep 17 00:00:00 2001 From: Andy Meneely Date: Thu, 9 Aug 2018 13:12:30 -0400 Subject: [PATCH] png: check magic bytes for well-formed files Closes #$250 --- CHANGELOG.md | 10 +++++++++- lib/squib/graphics/image.rb | 17 ++++++++++++++++- spec/data/images/a.png | Bin 0 -> 150 bytes spec/data/images/not_a_png.txt | 1 + spec/graphics/image_magicbytes_check.rb | 20 ++++++++++++++++++++ spec/spec_helper.rb | 4 ++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 spec/data/images/a.png create mode 100644 spec/data/images/not_a_png.txt create mode 100644 spec/graphics/image_magicbytes_check.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 418179f..c3e3182 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,15 @@ Squib follows [semantic versioning](http://semver.org). ## v0.15.0 / Unreleased -## v0.14.2 / Unreleased +Features: +* Added check for malformed PNG files (#250, #218) + +Docs: +* Documented the n-sided-ness of polygons and stars + +Special thanks to @lcarlsen + +## v0.14.2 / 2018-08-01 Features: * Sprues for DriveThruCards and printandplaygames!! (#247, from @blinks) diff --git a/lib/squib/graphics/image.rb b/lib/squib/graphics/image.rb index 7bfb719..3b10599 100644 --- a/lib/squib/graphics/image.rb +++ b/lib/squib/graphics/image.rb @@ -6,10 +6,25 @@ module Squib # @api private def cache_load_image(file) @img_cache ||= {} - @img_cache[file] || @img_cache[file] = Cairo::ImageSurface.from_png(file) + @img_cache[file] ||= open_png file end module_function :cache_load_image + # Open a PNG file, checking magic bytes if it's a real PNG + # Magic bytes taken from: + # https://en.wikipedia.org/wiki/List_of_file_signatures + # :nodoc: + # @api private + PNG_MAGIC = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] + def open_png(file) + if PNG_MAGIC == File.read(file, 8).bytes + return Cairo::ImageSurface.from_png(file) + else + raise ArgumentError.new("ERROR: #{file} is not a PNG file") + end + end + module_function :open_png + class Card # :nodoc: diff --git a/spec/data/images/a.png b/spec/data/images/a.png new file mode 100644 index 0000000000000000000000000000000000000000..883be2f4fdd54c79428b7d327bbd745f5064eb01 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2ryoCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#5eKJ$iULnVSq)G~HZvrm#5q4VH#M&W$Yo$~E=o--Nlj5G&n(GMaQE~LNYP7W n2a5A}x;Tb#Tu=V-|Gzy0>p!M{cg{pU2Wjwh^>bP0l+XkKwR|Nu literal 0 HcmV?d00001 diff --git a/spec/data/images/not_a_png.txt b/spec/data/images/not_a_png.txt new file mode 100644 index 0000000..51bb107 --- /dev/null +++ b/spec/data/images/not_a_png.txt @@ -0,0 +1 @@ +Not a PNG. diff --git a/spec/graphics/image_magicbytes_check.rb b/spec/graphics/image_magicbytes_check.rb new file mode 100644 index 0000000..869d276 --- /dev/null +++ b/spec/graphics/image_magicbytes_check.rb @@ -0,0 +1,20 @@ +require 'spec_helper' +require 'squib/graphics/image' + +describe Squib do + context :open_png do + + it 'opens a real image file' do + file = image_file('a.png') + expect(Squib.open_png(file)).to respond_to(:format) # loaded? + end + + it 'fails on a non-PNG file' do + file = image_file('not_a_png.txt') + expect { Squib.open_png(file) }. + to raise_error(ArgumentError, /is not a PNG file/) + + end + + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4f8b912..5c4fb9a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -42,6 +42,10 @@ def csv_file(file) "#{File.expand_path(File.dirname(__FILE__))}/data/csv/#{file}" end +def image_file(file) + "#{File.expand_path(File.dirname(__FILE__))}/data/images/#{file}" +end + def xlsx_file(file) "#{File.expand_path(File.dirname(__FILE__))}/data/xlsx/#{file}" end