From 5262b2900abd24d5990f3e585513ad38027e95e8 Mon Sep 17 00:00:00 2001 From: niloufar Date: Mon, 4 Nov 2019 21:09:20 +0900 Subject: [PATCH 01/10] Fix: Dll Loading --- ext/seven_zip_ruby/extconf.rb | 4 +-- ext/seven_zip_ruby/seven_zip_archive.cpp | 33 ++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/ext/seven_zip_ruby/extconf.rb b/ext/seven_zip_ruby/extconf.rb index b584429..44285b7 100644 --- a/ext/seven_zip_ruby/extconf.rb +++ b/ext/seven_zip_ruby/extconf.rb @@ -140,11 +140,11 @@ def main if (RUBY_PLATFORM.include?("mswin")) # mswin32 - $LIBS = "oleaut32.lib" + $LIBS = "oleaut32.lib shlwapi.lib" $CPPFLAGS = "/I.. /EHsc /DNDEBUG /DUSE_WIN32_FILE_API #{base_flag} #{$CPPFLAGS} " elsif (RUBY_PLATFORM.include?("mingw")) # MinGW - $LIBS = "-loleaut32 -static-libgcc -static-libstdc++" + $LIBS = "-loleaut32 -lshlwapi -static-libgcc -static-libstdc++" cpp0x_flag = [ "", "-std=gnu++11", "-std=c++11", "-std=gnu++0x", "-std=c++0x" ].find do |opt| try_compile(sample_cpp_source, "#{opt} -x c++ ") diff --git a/ext/seven_zip_ruby/seven_zip_archive.cpp b/ext/seven_zip_ruby/seven_zip_archive.cpp index 05319e1..4bc4238 100644 --- a/ext/seven_zip_ruby/seven_zip_archive.cpp +++ b/ext/seven_zip_ruby/seven_zip_archive.cpp @@ -1761,15 +1761,44 @@ STDMETHODIMP OutStream::SetSize(UInt64 size) } +#ifdef _WIN32 +#include "Shlwapi.h" +static HINSTANCE gDllInstance = NULL; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) +{ + // Perform actions based on the reason for calling. + switch( fdwReason ) + { + case DLL_PROCESS_ATTACH: + gDllInstance = hinstDLL; + break; + case DLL_PROCESS_DETACH: + gDllInstance = NULL; + break; + } + return TRUE; +} +#endif + extern "C" void Init_seven_zip_archive(void) { using namespace SevenZip; using namespace RubyCppUtil; #ifdef _WIN32 - gSevenZipHandle = LoadLibrary("./7z.dll"); + WCHAR modulePath[MAX_PATH]; + GetModuleFileNameW(gDllInstance, modulePath, _countof(modulePath)); + + SetDllDirectory(""); + + PathRemoveFileSpecW(modulePath); + PathAppendW(modulePath, L"7z.dll"); + gSevenZipHandle = LoadLibraryW(modulePath); if (!gSevenZipHandle){ - gSevenZipHandle = LoadLibrary("./7z64.dll"); + PathRemoveFileSpecW(modulePath); + PathAppendW(modulePath, L"7z64.dll"); + gSevenZipHandle = LoadLibraryW(modulePath); } #else gSevenZipHandle = dlopen("./7z.so", RTLD_NOW); From 6a03ddc396a4c6c17424fe3ff54bde915969782b Mon Sep 17 00:00:00 2001 From: niloufar Date: Mon, 11 Nov 2019 21:45:23 +0900 Subject: [PATCH 02/10] Fix: Extract Path --- lib/seven_zip_ruby/seven_zip_reader.rb | 17 ++++- test/res/test_reader_data.7z | Bin 0 -> 138 bytes test/res/test_reader_files.7z | Bin 0 -> 552 bytes test/test_seven_zip_reader.rb | 86 +++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100755 test/res/test_reader_data.7z create mode 100644 test/res/test_reader_files.7z create mode 100755 test/test_seven_zip_reader.rb diff --git a/lib/seven_zip_ruby/seven_zip_reader.rb b/lib/seven_zip_ruby/seven_zip_reader.rb index 378ad4f..482dfb6 100644 --- a/lib/seven_zip_ruby/seven_zip_reader.rb +++ b/lib/seven_zip_ruby/seven_zip_reader.rb @@ -462,13 +462,28 @@ def idx_prj.[](index) def file_proc(base_dir) # :nodoc: base_dir = base_dir.to_s + base_dir = File.expand_path(base_dir) return Proc.new do |type, arg| case(type) when :stream ret = nil arg_path = Pathname(arg.path) + rp = arg_path.cleanpath + if "..#{File::SEPARATOR}" == rp.to_s[0..2] + raise "#{arg.path} is Dangerous Path." + end if (arg.anti?) - arg_path.rmtree if (arg_path.exist?) + pwd = Dir.pwd + Dir.chdir(base_dir) + rp = File.join(".", arg_path.to_s) + begin + if (File.exist?(rp)) + require 'fileutils' + FileUtils.remove_entry_secure(rp) + end + ensure + Dir.chdir(pwd) rescue nil + end elsif (arg.file?) path = arg_path.expand_path(base_dir) path.parent.mkpath diff --git a/test/res/test_reader_data.7z b/test/res/test_reader_data.7z new file mode 100755 index 0000000000000000000000000000000000000000..2904d8c9cbb64ab19af1587454789531daef46c3 GIT binary patch literal 138 zcmXr7+Ou9=hJj^c_EKE|1_+3P(t&&4zG7tH_AF5^R!CGZuTtdYVqj!pV_@VIU|{EF zWMEWOWMtssVc_6mlr>ThVPIfol;nZx1yh2;3@HqW3?)FU2P7+in1Ml(L4=EufpvKi QbJ>imjG}Ce3<_Yy0Nw`@?f?J) literal 0 HcmV?d00001 diff --git a/test/res/test_reader_files.7z b/test/res/test_reader_files.7z new file mode 100644 index 0000000000000000000000000000000000000000..b2106250424e3bb403a49857e2d44f163c51d76b GIT binary patch literal 552 zcmV+@0@wXFdc3bE8~_B6sV}(Y0RR910000Z000000001<@W5!`0xSVRT>x^cjPL}R zai3VRVthT~>h&+*{2uI+LFQHS-Z2+Q$Nz^I-u}6q<$Cis@Z@uDerTuASMaNTdt(mF zWE-c5>Dh9CC7)eCnQ`C@ltO$Ys@R-G?VW^ghpMB*+Hy71CHko=%G`ErH`vFJ0*=y3i#;RtIe-@-VLp+A#FN!jI?8MzA zo=bxX_eq*WhjteOAb-;2>Fn%pGtzsLhu=T0gKCO{fZR8> z{ONd2chB#pyImOYkxag}*D=;e+pnxw{+lWf<1fvj$(eq>)}jy@&yH^Rk1uZXU24(I z#8CnW zJ^%m!004nA2d)p*IdAV*B-8%0a2SC=9!(6&5l3HCVs7e8-!M|nvXzx@^734yi)wh$asoLo>T qRsaA17Y2bz0SSPd00#>J00AQd0RaVF01yBG41mrG0XdyEmH+@?Wd(fz literal 0 HcmV?d00001 diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb new file mode 100755 index 0000000..0c6b854 --- /dev/null +++ b/test/test_seven_zip_reader.rb @@ -0,0 +1,86 @@ +# vim: tabstop=4 fileformat=linux fileencoding=utf-8 filetype=ruby + +require 'rubygems' +# gem install test-unit +require 'test/unit' + +STDERR.sync = true + +$basedir = File.dirname( $0 ) +$tmpdir = File.join( $basedir, "tmp" ) +$resourcedir = File.join( $basedir, "res" ) + +require 'seven_zip_ruby' + +class TestSevenZipReader < Test::Unit::TestCase +=begin + def setup + end + + def teardown + end +=end + + def test_reader_extract_data + formats = [ + ["7ZIP", "7z", "It's a 7z!\r\n"], + ] + formats.each do |e| + type, ext, text, = *e + pth = File.join( $resourcedir, "test_reader_data.#{ext}" ) + File.open( pth, "rb" ) do |file| + SevenZipRuby::Reader.open( file, :type => type ) do |szr| + smallest_file = szr.entries.select( &:file? ).first + data = szr.extract_data( smallest_file ) + data.force_encoding( Encoding::UTF_8 ) + assert_equal( text, data ) + end + end + end + end + + def test_reader_entries + pth = File.join( $resourcedir, "test_reader_files.7z" ) + File.open( pth, "rb" ) do |file| + SevenZipRuby::Reader.open( file ) do |szr| + ent = szr.entries + assert_equal( "The Flying Spaghetti Monster.txt", ent[0].path ) + assert_equal( "The Three Little Pigs.txt", ent[1].path ) + end + end + end + + def remove_tmp_entries( entries ) + entries.each do |f| + pth = File.join( $tmpdir, f ) + File.delete( pth ) if File.exist?( pth ) + end + end + + def test_reader_extract + Dir.mkdir( $tmpdir ) rescue nil + + entries = [ + "The Flying Spaghetti Monster.txt", + "The Three Little Pigs.txt" + ] + remove_tmp_entries( entries ) + + pth = File.join( $resourcedir, "test_reader_files.7z" ) + File.open( pth, "rb" ) do |file| + SevenZipRuby::Reader.open( file ) do |szr| + szr.extract_all( $tmpdir ) + end + end + + entries.each do |f| + pth = File.join( $tmpdir, f ) + assert( File.exist?( pth ) ) + end + + remove_tmp_entries( entries ) + Dir.rmdir( $tmpdir ) + end +end + + From 39420f41f8f2f7429609f1ea28823e2b70a5cd9e Mon Sep 17 00:00:00 2001 From: niloufar Date: Tue, 19 Nov 2019 00:46:10 +0900 Subject: [PATCH 03/10] Added Unit Test. --- test/res/The Flying Spaghetti Monster.txt | 3 + test/res/The Three Little Pigs.txt | 5 + test/res/test_reader_filename_cp932.7z | Bin 0 -> 712 bytes ...3\350\202\245\344\270\211\345\271\264.txt" | 3 + test/test_seven_zip_reader.rb | 64 ++++++--- test/test_seven_zip_writer.rb | 127 ++++++++++++++++++ 6 files changed, 185 insertions(+), 17 deletions(-) create mode 100755 test/res/The Flying Spaghetti Monster.txt create mode 100755 test/res/The Three Little Pigs.txt create mode 100755 test/res/test_reader_filename_cp932.7z create mode 100755 "test/res/\347\237\263\350\202\245\344\270\211\345\271\264.txt" create mode 100755 test/test_seven_zip_writer.rb diff --git a/test/res/The Flying Spaghetti Monster.txt b/test/res/The Flying Spaghetti Monster.txt new file mode 100755 index 0000000..4be351f --- /dev/null +++ b/test/res/The Flying Spaghetti Monster.txt @@ -0,0 +1,3 @@ +宇宙は空飛ぶスパゲッティ・モンスターによって創造された。これは空飛ぶスパゲッティ・モンスターが大酒を飲んだ後の事であった。 + +https://ja.wikipedia.org/wiki/%E7%A9%BA%E9%A3%9B%E3%81%B6%E3%82%B9%E3%83%91%E3%82%B2%E3%83%83%E3%83%86%E3%82%A3%E3%83%BB%E3%83%A2%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%BC%E6%95%99 diff --git a/test/res/The Three Little Pigs.txt b/test/res/The Three Little Pigs.txt new file mode 100755 index 0000000..3daeff2 --- /dev/null +++ b/test/res/The Three Little Pigs.txt @@ -0,0 +1,5 @@ +Little pig, little pig, let me come in. +No, no, by the hair on my chinny chin chin. +Then I'll huff, and I'll puff, and I'll blow your house in. + +https://en.wikipedia.org/wiki/The_Three_Little_Pigs diff --git a/test/res/test_reader_filename_cp932.7z b/test/res/test_reader_filename_cp932.7z new file mode 100755 index 0000000000000000000000000000000000000000..6bd07ff10e7415939b61d3ba174bebe7801c2162 GIT binary patch literal 712 zcmV;(0yq6Pdc3bE8~_9jF$4)t0ssI200015000000000D=reiX1I+?PT>x{U&JHwv z*K`=xUrCzx(YLg=5<}t-{z(T51;9+W8cJ?PK5LuEL#V076?nULtu>zQ=e@fs`=y-Y z8B`#BxQK+A=r)yYQnK8fW03FRb#C6!j}>2#MEcfv-*iN{c82}Y8tKjY2;GGJC`dT@ zpgvcJYlE+5ZSZOl$8>yie1f$8i)k#{!;&ThIIry2;U}^Z2)aEpT&9 z+DtOU(ygjOQ=im6Y!&|FPy~r$NV7MZkyTuw2F_d?FX8x)7EA2RckWBY+!4FoMWPu$1ZkD(J z_XrYNeKkwn1`2cGaromK4lH{>UAUDjO?u6G%x$%99ZM_%N@ z6Q^_49?~E2Z;Qj(i9=HcO#m(Ey>*E~_K1Xp-M{19jY6GUYK{p{bLR?U-hd^FkYevL zWG^uQ009IB009YtP5=iB0RRCZAprmkgU$d53IQq3kih@|1pyff0000000000000pa u0P}aHfC)}?UM>K10C)g&0000P02B%V0F6}gI{2N{0Tl)T03ZMW0002u0z(r3 literal 0 HcmV?d00001 diff --git "a/test/res/\347\237\263\350\202\245\344\270\211\345\271\264.txt" "b/test/res/\347\237\263\350\202\245\344\270\211\345\271\264.txt" new file mode 100755 index 0000000..54763ff --- /dev/null +++ "b/test/res/\347\237\263\350\202\245\344\270\211\345\271\264.txt" @@ -0,0 +1,3 @@ +狐たちの間では、みんなが痛い目に遭っている彦一に一杯食わせようと企む奴は少なくない。ある狐は、夜のうちに彦一の家の畑に大量の石を投げ入れ、近くに隠れて様子をうかがっていた。翌朝になって畑にやって来た彦一は驚いたが、これが狐の仕業だと気付くと、わざと嬉しそうな顔をして、「こりゃ助かった。石の肥料は三年はもつ。これが馬の糞だったら大変な所じゃった」と、狐に聞こえるような大声で嘘をついた。これを真に受けた狐はその夜に石を全部取り除き、代わりに馬の糞をどっさり投げ入れた(馬の糞は良い肥料になる)。翌朝、彦一は「困った困った」と言いながらご機嫌な顔で畑を耕し、狐はこれで彦一を困らせてやったと満足して帰って行くのだった。 + +https://ja.wikipedia.org/wiki/%E5%BD%A6%E4%B8%80 \ No newline at end of file diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb index 0c6b854..bf28180 100755 --- a/test/test_seven_zip_reader.rb +++ b/test/test_seven_zip_reader.rb @@ -13,13 +13,34 @@ require 'seven_zip_ruby' class TestSevenZipReader < Test::Unit::TestCase -=begin - def setup + + def self.startup + self.remove_tmpdir + end + + def self.shutdown + self.remove_tmpdir + end + + def tmpdir + unless File.exist?( $tmpdir ) + Dir.mkdir( $tmpdir ) rescue nil + end + $tmpdir + end + + def self.remove_tmpdir + if File.exist?( $tmpdir ) + Dir.rmdir( $tmpdir ) rescue nil + end end - def teardown + def remove_tmp_entries( entries ) + entries.each do |f| + pth = File.join( $tmpdir, f ) + File.delete( pth ) if File.exist?( pth ) + end end -=end def test_reader_extract_data formats = [ @@ -30,8 +51,8 @@ def test_reader_extract_data pth = File.join( $resourcedir, "test_reader_data.#{ext}" ) File.open( pth, "rb" ) do |file| SevenZipRuby::Reader.open( file, :type => type ) do |szr| - smallest_file = szr.entries.select( &:file? ).first - data = szr.extract_data( smallest_file ) + first_file = szr.entries.select( &:file? ).first + data = szr.extract_data( first_file ) data.force_encoding( Encoding::UTF_8 ) assert_equal( text, data ) end @@ -50,15 +71,8 @@ def test_reader_entries end end - def remove_tmp_entries( entries ) - entries.each do |f| - pth = File.join( $tmpdir, f ) - File.delete( pth ) if File.exist?( pth ) - end - end - def test_reader_extract - Dir.mkdir( $tmpdir ) rescue nil + tmp = tmpdir() entries = [ "The Flying Spaghetti Monster.txt", @@ -69,18 +83,34 @@ def test_reader_extract pth = File.join( $resourcedir, "test_reader_files.7z" ) File.open( pth, "rb" ) do |file| SevenZipRuby::Reader.open( file ) do |szr| - szr.extract_all( $tmpdir ) + szr.extract_all( tmp ) end end entries.each do |f| - pth = File.join( $tmpdir, f ) + pth = File.join( tmp, f ) assert( File.exist?( pth ) ) end remove_tmp_entries( entries ) - Dir.rmdir( $tmpdir ) end + + def test_reader_filepath_encoding_cp932 + tmp = tmpdir() + + pth = File.join( $resourcedir, "test_reader_filename_cp932.7z" ) + File.open( pth, "rb" ) do |file| + SevenZipRuby::Reader.open( file ) do |szr| + ent = szr.entries + assert_equal( "石肥三年.txt", ent[0].path ) + szr.extract_all( tmp ) + end + end + assert( File.exist?( File.join( tmp, "石肥三年.txt" ) ) ) + + remove_tmp_entries( ["石肥三年.txt"] ) + end + end diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb new file mode 100755 index 0000000..de8df6f --- /dev/null +++ b/test/test_seven_zip_writer.rb @@ -0,0 +1,127 @@ +# vim: tabstop=4 fileformat=linux fileencoding=utf-8 filetype=ruby + +require 'rubygems' +# gem install test-unit +require 'test/unit' + +STDERR.sync = true + +$basedir = File.dirname( $0 ) +$tmpdir = File.join( $basedir, "tmp" ) +$resourcedir = File.join( $basedir, "res" ) + +#gem 'seven_zip_ruby_am', '< 1.2.6' +require 'seven_zip_ruby' +require 'stringio' + +class TestSevenZipWriter < Test::Unit::TestCase + + def test_writer_files + entries = [ + "The Flying Spaghetti Monster.txt", + "The Three Little Pigs.txt", + "石肥三年.txt" + ] + + file = StringIO.new( "test_writer_files.7z", "w+b" ) + SevenZipRuby::Writer.open( file ) do |szw| + Dir.chdir( $resourcedir ) do |dummy| + entries.each do |e| + szw.add_file( e ) + end + end + end + + file.rewind + SevenZipRuby::Reader.open( file ) do |szr| + ent = szr.entries + assert_equal( entries.size, ent.size ) + assert_equal( entries[0], ent[0].path ) + assert_equal( entries[1], ent[1].path ) + assert_equal( entries[2], ent[2].path ) + end + end + + def test_writer_encrypt + require 'digest/md5' + password = Random.rand + password = Digest::MD5.hexdigest( password.to_s ) + + fl = "The Three Little Pigs.txt" + + file = StringIO.new( "test_writer_crypt.7z", "w+b" ) + SevenZipRuby::Writer.open( file, :password => password ) do |szw| + Dir.chdir( $resourcedir ) do |dummy| + szw.add_file( fl ) + end + end + + file.rewind + SevenZipRuby::Reader.open( file ) do |szr| + first_file = szr.entries.select( &:file? ).first + assert_equal( fl, first_file.path ) + assert_raise( StandardError ) do + data = szr.extract_data( first_file ) + flunk( "The archive could be opened without a password." ) + end + end + + # SevenZipRuby::InvalidArchive is not thrown. +# file.rewind +# SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| +# first_file = szr.entries.select( &:file? ).first +# assert_equal( fl, first_file.path ) +# assert_raise( SevenZipRuby::InvalidArchive ) do +# data = szr.extract_data( first_file ) +# flunk( "The archive could be opened with an incollect password." ) +# end +# end + + file.rewind + SevenZipRuby::Reader.open( file, :password => password ) do |szr| + ent = szr.entries + assert_equal( fl, ent[0].path ) + end + end + + def test_writer_encrypt_header + require 'digest/md5' + password = Random.rand + password = Digest::MD5.hexdigest( password.to_s ) + + fl = "The Three Little Pigs.txt" + + file = StringIO.new( "test_writer_crypt.7z", "w+b" ) + SevenZipRuby::Writer.open( file, :password => password ) do |szw| + szw.header_encryption = true + Dir.chdir( $resourcedir ) do |dummy| + szw.add_file( fl ) + end + end + + file.rewind + # StandardError: Invalid file format. open + assert_raise( StandardError ) do + SevenZipRuby::Reader.open( file ) do |szr| + flunk( "The archive could be opened without a password." ) + end + end + + file.rewind + # StandardError: Invalid file format. open + assert_raise( StandardError ) do + SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| + flunk( "The archive could be opened with an incollect password." ) + end + end + + file.rewind + SevenZipRuby::Reader.open( file, :password => password ) do |szr| + ent = szr.entries + assert_equal( fl, ent[0].path ) + end + end + +end + + From b7b9afeb588241b42af7dd5a3279221bc6ba97b8 Mon Sep 17 00:00:00 2001 From: niloufar Date: Wed, 20 Nov 2019 23:46:08 +0900 Subject: [PATCH 04/10] Improved Unit Test. --- test/test_seven_zip_reader.rb | 2 ++ test/test_seven_zip_writer.rb | 33 ++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb index bf28180..d1824e0 100755 --- a/test/test_seven_zip_reader.rb +++ b/test/test_seven_zip_reader.rb @@ -10,6 +10,7 @@ $tmpdir = File.join( $basedir, "tmp" ) $resourcedir = File.join( $basedir, "res" ) +#gem 'seven_zip_ruby_am', '< 1.2.6' require 'seven_zip_ruby' class TestSevenZipReader < Test::Unit::TestCase @@ -114,3 +115,4 @@ def test_reader_filepath_encoding_cp932 end + diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb index de8df6f..88a47b6 100755 --- a/test/test_seven_zip_writer.rb +++ b/test/test_seven_zip_writer.rb @@ -40,12 +40,16 @@ def test_writer_files assert_equal( entries[1], ent[1].path ) assert_equal( entries[2], ent[2].path ) end + + file.close end def test_writer_encrypt require 'digest/md5' password = Random.rand - password = Digest::MD5.hexdigest( password.to_s ) + notify( "Random.rand: #{password}" ) + password = Digest::MD5.digest( password.to_s ) + password = [password].pack( "m0" ) # base64 fl = "The Three Little Pigs.txt" @@ -66,15 +70,18 @@ def test_writer_encrypt end end - # SevenZipRuby::InvalidArchive is not thrown. # file.rewind -# SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| -# first_file = szr.entries.select( &:file? ).first -# assert_equal( fl, first_file.path ) -# assert_raise( SevenZipRuby::InvalidArchive ) do -# data = szr.extract_data( first_file ) -# flunk( "The archive could be opened with an incollect password." ) +# begin +# SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| +# first_file = szr.entries.select( &:file? ).first +# assert_equal( fl, first_file.path ) +# assert_raise( SevenZipRuby::InvalidArchive ) do +# data = szr.extract_data( first_file ) +# flunk( "The archive could be opened with an incollect password." ) +# end # end +# rescue SevenZipRuby::InvalidOperation => err +# # ignore # end file.rewind @@ -82,12 +89,17 @@ def test_writer_encrypt ent = szr.entries assert_equal( fl, ent[0].path ) end + + file.close end def test_writer_encrypt_header require 'digest/md5' password = Random.rand - password = Digest::MD5.hexdigest( password.to_s ) + notify( "Random.rand: #{password}" ) + password = Digest::MD5.digest( password.to_s ) + password = [password].pack( "m0" ) # base64 + fl = "The Three Little Pigs.txt" @@ -120,8 +132,11 @@ def test_writer_encrypt_header ent = szr.entries assert_equal( fl, ent[0].path ) end + + file.close end end + From 384775a32e4c4be46de5ddbd94e4e013e8361d0d Mon Sep 17 00:00:00 2001 From: niloufar Date: Wed, 20 Nov 2019 23:47:29 +0900 Subject: [PATCH 05/10] Added Unit Test. --- test/test_seven_zip_reader.rb | 69 +++++++++++++++++++++++++++++++++++ test/test_seven_zip_writer.rb | 39 ++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb index d1824e0..27f62fe 100755 --- a/test/test_seven_zip_reader.rb +++ b/test/test_seven_zip_reader.rb @@ -112,6 +112,75 @@ def test_reader_filepath_encoding_cp932 remove_tmp_entries( ["石肥三年.txt"] ) end + def test_reader_extract_zs + data = < err + assert_match( /Dangerous Path/i, err.message ) + safety = true + end + end + rescue SevenZipRuby::InvalidOperation => err + # ignore + end + unless safety + notify( "The expected exception is not thrown." ) + end + assert_path_not_exist( File.join( tmp, file_name ) ) + + file.rewind + # szr.extract_all + safety = false + begin + SevenZipRuby::Reader.open( file ) do |szr| + ent = szr.entries + begin + szr.extract_all( tmp_tmp ) +# notify( "Vulnerable ?" ) + rescue RuntimeError => err + assert_match( /Dangerous Path/i, err.message ) + safety = true + end + end + rescue SevenZipRuby::InvalidOperation => err + # ignore + end + unless safety + notify( "The expected exception is not thrown." ) + end + assert_path_not_exist( File.join( tmp, file_name ) ) + + file.close + + Dir.rmdir( tmp_tmp ) if Dir.exist?( tmp_tmp ) + end + end diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb index 88a47b6..b4b17be 100755 --- a/test/test_seven_zip_writer.rb +++ b/test/test_seven_zip_writer.rb @@ -136,6 +136,45 @@ def test_writer_encrypt_header file.close end + def test_writer_levels + fl = '石肥三年.txt' + pth = File.join( $resourcedir, fl ) + data = File.read( pth, :encoding => Encoding::UTF_8 ) + + ["LZMA", "LZMA2", "PPMd", "BZIP2", "DEFLATE"].each do |method| + [0, 1, 3, 5, 7, 9].each do |level| + msg = "method: #{method}, level: #{level}." + __test_writer_levels_compress( fl, data, method, level, msg ) + end + end + end + + def __test_writer_levels_compress( i_name, i_data, i_method, i_level, i_message ) + file = StringIO.new( "test_writer_levels.7z", "w+b" ) + SevenZipRuby::Writer.open( file ) do |szw| + szw.method = i_method +# szw.multi_thread = true + szw.level = i_level + + d = i_data.dup + szw.add_data( d, i_name ) + szw.compress + d.replace( "\0" * d.size ) + end + + file.rewind + SevenZipRuby::Reader.open( file ) do |szr| + first_file = szr.entries.select( &:file? ).first + assert_equal( i_name, first_file.path, i_message ) + + d = szr.extract_data( first_file ) + d.force_encoding( i_data.encoding ) + assert_equal( i_data, d, i_message ) + end + + file.close + end + end From 61b4c9d29465b55d973794f70eeeb2cd73242644 Mon Sep 17 00:00:00 2001 From: niloufar Date: Thu, 21 Nov 2019 00:58:37 +0900 Subject: [PATCH 06/10] typo --- test/test_seven_zip_reader.rb | 2 +- test/test_seven_zip_writer.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb index 27f62fe..75e8c5b 100755 --- a/test/test_seven_zip_reader.rb +++ b/test/test_seven_zip_reader.rb @@ -1,4 +1,4 @@ -# vim: tabstop=4 fileformat=linux fileencoding=utf-8 filetype=ruby +# vim: tabstop=4 fileformat=unix fileencoding=utf-8 filetype=ruby require 'rubygems' # gem install test-unit diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb index b4b17be..2822e53 100755 --- a/test/test_seven_zip_writer.rb +++ b/test/test_seven_zip_writer.rb @@ -1,4 +1,4 @@ -# vim: tabstop=4 fileformat=linux fileencoding=utf-8 filetype=ruby +# vim: tabstop=4 fileformat=unix fileencoding=utf-8 filetype=ruby require 'rubygems' # gem install test-unit From 877e1544d72781f13c26e67e00729bd8568ac939 Mon Sep 17 00:00:00 2001 From: niloufar Date: Thu, 21 Nov 2019 23:59:17 +0900 Subject: [PATCH 07/10] Added Unit Test. --- test/test_seven_zip_writer.rb | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb index 2822e53..3ff13e6 100755 --- a/test/test_seven_zip_writer.rb +++ b/test/test_seven_zip_writer.rb @@ -70,19 +70,22 @@ def test_writer_encrypt end end -# file.rewind -# begin -# SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| -# first_file = szr.entries.select( &:file? ).first -# assert_equal( fl, first_file.path ) -# assert_raise( SevenZipRuby::InvalidArchive ) do -# data = szr.extract_data( first_file ) -# flunk( "The archive could be opened with an incollect password." ) -# end -# end -# rescue SevenZipRuby::InvalidOperation => err -# # ignore -# end + file.rewind + begin + SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| + first_file = szr.entries.select( &:file? ).first + assert_equal( fl, first_file.path ) + # 7z 19.00 throws SevenZipRuby::InvalidArchive. + assert_raise( SevenZipRuby::InvalidArchive ) do + data = szr.extract_data( first_file ) + # p7zip 16.02 returns nil. + raise SevenZipRuby::InvalidArchive.new if data.nil? + flunk( "The archive could be opened with an incollect password." ) + end + end + rescue SevenZipRuby::InvalidOperation => err + # ignore + end file.rewind SevenZipRuby::Reader.open( file, :password => password ) do |szr| From 8915f6b9ef003043bf6e01eff993c762bdbac4ff Mon Sep 17 00:00:00 2001 From: niloufar Date: Sat, 23 Nov 2019 15:51:24 +0900 Subject: [PATCH 08/10] typo --- test/test_seven_zip_writer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_seven_zip_writer.rb b/test/test_seven_zip_writer.rb index 3ff13e6..dc6bc8d 100755 --- a/test/test_seven_zip_writer.rb +++ b/test/test_seven_zip_writer.rb @@ -80,7 +80,7 @@ def test_writer_encrypt data = szr.extract_data( first_file ) # p7zip 16.02 returns nil. raise SevenZipRuby::InvalidArchive.new if data.nil? - flunk( "The archive could be opened with an incollect password." ) + flunk( "The archive could be opened with an incorrect password." ) end end rescue SevenZipRuby::InvalidOperation => err @@ -126,7 +126,7 @@ def test_writer_encrypt_header # StandardError: Invalid file format. open assert_raise( StandardError ) do SevenZipRuby::Reader.open( file, :password => "INCORRECT PASSWORD" ) do |szr| - flunk( "The archive could be opened with an incollect password." ) + flunk( "The archive could be opened with an incorrect password." ) end end From cfa32bbc5df4e30d885e99b9b73a3f7f9cc53161 Mon Sep 17 00:00:00 2001 From: niloufar Date: Sat, 23 Nov 2019 16:20:21 +0900 Subject: [PATCH 09/10] The code was improved. Fixed an error message when decryption of wrong password failed. Added taint marks to file paths in archives. --- ext/seven_zip_ruby/seven_zip_archive.cpp | 6 +++++- ext/seven_zip_ruby/utils.cpp | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ext/seven_zip_ruby/seven_zip_archive.cpp b/ext/seven_zip_ruby/seven_zip_archive.cpp index 4bc4238..ff09d44 100644 --- a/ext/seven_zip_ruby/seven_zip_archive.cpp +++ b/ext/seven_zip_ruby/seven_zip_archive.cpp @@ -317,7 +317,11 @@ VALUE ArchiveReader::open(VALUE in_stream, VALUE param) checkState(STATE_INITIAL, "Open error"); if (ret != S_OK){ - throw RubyCppUtil::RubyException("Invalid file format. open"); + if (m_password_specified){ + throw RubyCppUtil::RubyException("Invalid file format. open. or password is incorrect."); + }else{ + throw RubyCppUtil::RubyException("Invalid file format. open."); + } } m_state = STATE_OPENED; diff --git a/ext/seven_zip_ruby/utils.cpp b/ext/seven_zip_ruby/utils.cpp index 8e1639b..9d9bfd4 100644 --- a/ext/seven_zip_ruby/utils.cpp +++ b/ext/seven_zip_ruby/utils.cpp @@ -448,13 +448,13 @@ VALUE ConvertBstrToString(const BSTR &bstr) const int char_count = SysStringLen(bstr); #ifdef _WIN32 const int len = WideCharToMultiByte(CP_UTF8, 0, bstr, char_count, NULL, 0, NULL, NULL); - VALUE str = rb_str_new(NULL, len); + VALUE str = rb_tainted_str_new(NULL, len); WideCharToMultiByte(CP_UTF8, 0, bstr, char_count, RSTRING_PTR(str), len, NULL, NULL); #else size_t len; Utf16_To_Utf8(NULL, &len, bstr, char_count); - VALUE str = rb_str_new(NULL, len); + VALUE str = rb_tainted_str_new(NULL, len); Utf16_To_Utf8(RSTRING_PTR(str), &len, bstr, char_count); #endif return str; From 57309ca59811d773d6e73840f1e1c1a74fe75cf2 Mon Sep 17 00:00:00 2001 From: niloufar Date: Thu, 19 Dec 2019 23:33:35 +0900 Subject: [PATCH 10/10] The exception to be thrown was changed to an appropriate class. --- lib/seven_zip_ruby/seven_zip_reader.rb | 2 +- test/test_seven_zip_reader.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/seven_zip_ruby/seven_zip_reader.rb b/lib/seven_zip_ruby/seven_zip_reader.rb index 482dfb6..6e6be51 100644 --- a/lib/seven_zip_ruby/seven_zip_reader.rb +++ b/lib/seven_zip_ruby/seven_zip_reader.rb @@ -470,7 +470,7 @@ def file_proc(base_dir) # :nodoc: arg_path = Pathname(arg.path) rp = arg_path.cleanpath if "..#{File::SEPARATOR}" == rp.to_s[0..2] - raise "#{arg.path} is Dangerous Path." + raise InvalidArchive.new("#{arg.path} is Dangerous Path.") end if (arg.anti?) pwd = Dir.pwd diff --git a/test/test_seven_zip_reader.rb b/test/test_seven_zip_reader.rb index 75e8c5b..72da1b0 100755 --- a/test/test_seven_zip_reader.rb +++ b/test/test_seven_zip_reader.rb @@ -141,7 +141,7 @@ def test_reader_extract_zs begin szr.extract( ent[0].path, tmp_tmp ) # notify( "Vulnerable ?" ) - rescue RuntimeError => err + rescue SevenZipRuby::InvalidArchive => err assert_match( /Dangerous Path/i, err.message ) safety = true end @@ -163,7 +163,7 @@ def test_reader_extract_zs begin szr.extract_all( tmp_tmp ) # notify( "Vulnerable ?" ) - rescue RuntimeError => err + rescue SevenZipRuby::InvalidArchive => err assert_match( /Dangerous Path/i, err.message ) safety = true end