guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: supporting EOL ruby in Guix


From: Alex Vong
Subject: Re: supporting EOL ruby in Guix
Date: Sat, 24 Nov 2018 21:44:59 +0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Pjotr Prins <address@hidden> writes:

> I think we can now drop the unsupported versions. I was using 1.8
> until quite recently ;). These packages can be put into channels for
> those who need that.
>
Ok, so we can drop them for guix. But I think we should still try to fix
as many CVEs as possible even if we were to put them into channels (thus
not officially supported). Please let me know if someone want to put it
into channels!

For 1.8, I have the following patch (it only include security fixes
prior to May 2018) which can be applied to current master
(083ce0ad5ecd10c6033bbdef5ddfcc2f58a7b800):

From 4abe2e6cca013422a20b06104e5ab1230446a6cb Mon Sep 17 00:00:00 2001
From: Alex Vong <address@hidden>
Date: Fri, 23 Nov 2018 06:34:10 +0800
Subject: [PATCH] gnu: ruby-1.8: Fix CVE-2013-4164, CVE-2014-{8080,8090},
 CVE-2015-1855, CVE-2017-{0898,10784,17405,17742,17790} and
 CVE-2018-{6914,8777,8778,8779,8780}.

* gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch,
gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch,
gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch,
gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch,
gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch,
gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch: New files.
* gnu/local.mk (dist_patch_DATA): Add them.
* gnu/packages/ruby.scm (ruby-1.8)[source]: Use them.
---
 gnu/local.mk                                  |  17 +
 .../patches/ruby-1.8-CVE-2013-4164.patch      |  84 ++++
 .../patches/ruby-1.8-CVE-2014-8080.patch      |  76 ++++
 .../patches/ruby-1.8-CVE-2014-8090.patch      | 120 ++++++
 .../patches/ruby-1.8-CVE-2015-1855.patch      | 270 ++++++++++++
 .../patches/ruby-1.8-CVE-2017-0898.patch      | 110 +++++
 .../patches/ruby-1.8-CVE-2017-10784.patch     |  99 +++++
 .../patches/ruby-1.8-CVE-2017-17405.patch     |  62 +++
 .../patches/ruby-1.8-CVE-2017-17742-pre.patch | 161 +++++++
 .../patches/ruby-1.8-CVE-2017-17742.patch     | 132 ++++++
 .../patches/ruby-1.8-CVE-2017-17790.patch     |  32 ++
 .../patches/ruby-1.8-CVE-2018-6914.patch      |  99 +++++
 ...1.8-CVE-2018-8777+CVE-2017-17742-pre.patch | 366 ++++++++++++++++
 .../patches/ruby-1.8-CVE-2018-8777.patch      | 394 ++++++++++++++++++
 .../patches/ruby-1.8-CVE-2018-8778.patch      |  67 +++
 .../patches/ruby-1.8-CVE-2018-8779.patch      |  99 +++++
 ...-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch |  52 +++
 .../patches/ruby-1.8-CVE-2018-8780.patch      | 114 +++++
 gnu/packages/ruby.scm                         |  20 +-
 19 files changed, 2373 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch
 create mode 100644 
gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch
 create mode 100644 
gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch
 create mode 100644 gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index c56278e93..83cc4cfe3 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1127,6 +1127,23 @@ dist_patch_DATA =                                        
        \
   %D%/packages/patches/rpcbind-CVE-2017-8779.patch             \
   %D%/packages/patches/rtags-separate-rct.patch                        \
   %D%/packages/patches/racket-store-checksum-override.patch    \
+  %D%/packages/patches/ruby-1.8-CVE-2013-4164.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2014-8080.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2014-8090.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2015-1855.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2017-0898.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2017-10784.patch           \
+  %D%/packages/patches/ruby-1.8-CVE-2017-17405.patch           \
+  %D%/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch       \
+  %D%/packages/patches/ruby-1.8-CVE-2017-17742.patch           \
+  %D%/packages/patches/ruby-1.8-CVE-2017-17790.patch           \
+  %D%/packages/patches/ruby-1.8-CVE-2018-6914.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8777.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8778.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8779.patch            \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch  \
+  %D%/packages/patches/ruby-1.8-CVE-2018-8780.patch            \
   %D%/packages/patches/ruby-rubygems-276-for-ruby24.patch      \
   %D%/packages/patches/ruby-concurrent-ignore-broken-test.patch        \
   %D%/packages/patches/ruby-concurrent-test-arm.patch          \
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch
new file mode 100644
index 000000000..5838d2b14
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2013-4164.patch
@@ -0,0 +1,84 @@
+Fix CVE-2013-4164:
+
+https://www.ruby-lang.org/en/news/2013/11/22/heap-overflow-in-floating-point-parsing-cve-2013-4164/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4164
+https://security-tracker.debian.org/tracker/CVE-2013-4164
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Description: Fix Heap Overflow in Floating Point Parsing
+ This vulnerability is tracked with CVE-2013-4164.
+ .
+ https://www.ruby-lang.org/en/news/2013/11/22/ruby-1-9-3-p484-is-released/
+Origin: backport, 
https://bugs.ruby-lang.org/projects/ruby-193/repository/revisions/43776/diff
+ https://bugs.ruby-lang.org/projects/ruby-193/repository/revisions/43782/diff
+Bug-Debian: http://bugs.debian.org/730189
+Forwarded: not-needed
+Applied-Upstream: 1.9.3-p484, 2.0.0-p353
+Last-Update: 2013-11-29
+
+--- a/util.c
++++ b/util.c
+@@ -892,6 +892,11 @@ extern void *MALLOC(size_t);
+ #else
+ #define MALLOC malloc
+ #endif
++#ifdef FREE
++extern void FREE(void*);
++#else
++#define FREE free
++#endif
+ 
+ #ifndef Omit_Private_Memory
+ #ifndef PRIVATE_MEM
+@@ -1176,7 +1181,7 @@ Balloc(int k)
+ #endif
+ 
+     ACQUIRE_DTOA_LOCK(0);
+-    if ((rv = freelist[k]) != 0) {
++    if (k <= Kmax && (rv = freelist[k]) != 0) {
+         freelist[k] = rv->next;
+     }
+     else {
+@@ -1186,7 +1191,7 @@ Balloc(int k)
+ #else
+         len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+                 /sizeof(double);
+-        if (pmem_next - private_mem + len <= PRIVATE_mem) {
++        if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
+             rv = (Bigint*)pmem_next;
+             pmem_next += len;
+         }
+@@ -1205,6 +1210,10 @@ static void
+ Bfree(Bigint *v)
+ {
+     if (v) {
++        if (v->k > Kmax) {
++            FREE(v);
++            return;
++        }
+         ACQUIRE_DTOA_LOCK(0);
+         v->next = freelist[v->k];
+         freelist[v->k] = v;
+@@ -2200,6 +2209,7 @@ break2:
+         for (; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+             nz++;
++            if (nf > DBL_DIG * 4) continue;
+             if (c -= '0') {
+                 nf += nz;
+                 for (i = 1; i < nz; i++)
+--- a/test/ruby/test_float.rb
++++ b/test/ruby/test_float.rb
+@@ -171,4 +171,9 @@ class TestFloat < Test::Unit::TestCase
+     assert_raise(ArgumentError) { 1.0 < nil }
+     assert_raise(ArgumentError) { 1.0 <= nil }
+   end
++
++  def test_long_string
++    assert(10.0 - ("1."+"1"*300000).to_f*9 < 0.000001)
++  end
++
+ end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch
new file mode 100644
index 000000000..169b41379
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2014-8080.patch
@@ -0,0 +1,76 @@
+Fix CVE-2014-8080:
+
+https://www.ruby-lang.org/en/news/2014/10/27/rexml-dos-cve-2014-8080/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-8080
+https://security-tracker.debian.org/tracker/CVE-2014-8080
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Description: Fix CVE-2014-8080
+Origin: upstream, 
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48161
+Forwarded: not-needed
+Author: Alessandro Ghedini <address@hidden>
+Last-Update: 2015-02-07
+
+--- a/lib/rexml/entity.rb
++++ b/lib/rexml/entity.rb
+@@ -138,8 +138,14 @@
+                               matches = @value.scan(PEREFERENCE_RE)
+                               rv = @value.clone
+                               if @parent
++                                      sum = 0
+                                       matches.each do |entity_reference|
+                                               entity_value = @parent.entity( 
entity_reference[0] )
++                                              if sum + entity_value.bytesize 
> Document.entity_expansion_text_limit
++                                                      raise "entity expansion 
has grown too large"
++                                              else
++                                                      sum += 
entity_value.bytesize
++                                              end
+                                               rv.gsub!( 
/%#{entity_reference};/um, entity_value )
+                                       end
+                               end
+--- a/test/rexml/test_document.rb
++++ b/test/rexml/test_document.rb
+@@ -26,6 +26,20 @@
+ </member>
+ EOF
+ 
++    XML_WITH_NESTED_PARAMETER_ENTITY = <<EOF
++<!DOCTYPE root [
++  <!ENTITY % a "BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.">
++  <!ENTITY % b "%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;">
++  <!ENTITY % c "%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;">
++  <!ENTITY % d "%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;">
++  <!ENTITY % e "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;">
++  <!ENTITY % f "%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;">
++  <!ENTITY % g "%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;">
++  <!ENTITY test "test %g;">
++]>
++<cd></cd>
++EOF
++
+   XML_WITH_4_ENTITY_EXPANSION = <<EOF
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE member [
+@@ -62,6 +76,19 @@
+     end
+   ensure
+     REXML::Document.entity_expansion_limit = 10000
++  end
++
++  def test_entity_expansion_limit_for_parameter_entity
++    assert_raise(REXML::ParseException) do
++      REXML::Document.new(XML_WITH_NESTED_PARAMETER_ENTITY)
++    end
++    REXML::Document.entity_expansion_limit = 100
++    assert_equal(100, REXML::Document.entity_expansion_limit)
++    assert_raise(REXML::ParseException) do
++      REXML::Document.new(XML_WITH_NESTED_PARAMETER_ENTITY)
++    end
++  ensure
++    REXML::Document.entity_expansion_limit = 10000
+   end
+ 
+   def test_entity_string_limit
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch
new file mode 100644
index 000000000..e6588dcb8
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2014-8090.patch
@@ -0,0 +1,120 @@
+Fix CVE-2014-8090:
+
+https://www.ruby-lang.org/en/news/2014/11/13/rexml-dos-cve-2014-8090/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-8090
+https://security-tracker.debian.org/tracker/CVE-2014-8090
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Description: Fix CVE-2014-8090
+Origin: upstream, 
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48402
+Forwarded: not-needed
+Author: Alessandro Ghedini <address@hidden>
+Last-Update: 2015-02-07
+
+--- a/lib/rexml/document.rb
++++ b/lib/rexml/document.rb
+@@ -235,6 +235,10 @@
+       end
+     end
+ 
++    def document
++      self
++    end
++
+               private
+               def build( source )
+       Parsers::TreeParser.new( source, self ).parse
+--- a/lib/rexml/entity.rb
++++ b/lib/rexml/entity.rb
+@@ -157,6 +157,7 @@
+ 
+       # This is a set of entity constants -- the ones defined in the XML
+       # specification.  These are +gt+, +lt+, +amp+, +quot+ and +apos+.
++      # CAUTION: these entities does not have parent and document
+       module EntityConst
+               # +>+
+               GT = Entity.new( 'gt', '>' )
+--- a/test/rexml/test_document.rb
++++ b/test/rexml/test_document.rb
+@@ -26,6 +26,22 @@
+ </member>
+ EOF
+ 
++    XML_WITH_NESTED_EMPTY_ENTITY = <<EOF
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE member [
++  <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
++  <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
++  <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
++  <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
++  <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
++  <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
++  <!ENTITY g "">
++]>
++<member>
+++&a;
++</member>
++EOF
++
+     XML_WITH_NESTED_PARAMETER_ENTITY = <<EOF
+ <!DOCTYPE root [
+   <!ENTITY % a "BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.">
+@@ -40,6 +56,20 @@
+ <cd></cd>
+ EOF
+ 
++    XML_WITH_NESTED_EMPTY_PARAMETER_ENTITY = <<EOF
++<!DOCTYPE root [
++  <!ENTITY % a "">
++  <!ENTITY % b "%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;">
++  <!ENTITY % c "%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;">
++  <!ENTITY % d "%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;">
++  <!ENTITY % e "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;">
++  <!ENTITY % f "%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;">
++  <!ENTITY % g "%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;">
++  <!ENTITY test "test %g;">
++]>
++<cd></cd>
++EOF
++
+   XML_WITH_4_ENTITY_EXPANSION = <<EOF
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE member [
+@@ -66,6 +96,18 @@
+     end
+     assert_equal(101, doc.entity_expansion_count)
+ 
++    doc = REXML::Document.new(XML_WITH_NESTED_EMPTY_ENTITY)
++    assert_raise(RuntimeError) do
++      doc.root.children.first.value
++    end
++    REXML::Document.entity_expansion_limit = 100
++    assert_equal(100, REXML::Document.entity_expansion_limit)
++    doc = REXML::Document.new(XML_WITH_NESTED_EMPTY_ENTITY)
++    assert_raise(RuntimeError) do
++      doc.root.children.first.value
++    end
++    assert_equal(101, doc.entity_expansion_count)
++
+     REXML::Document.entity_expansion_limit = 4
+     doc = REXML::Document.new(XML_WITH_4_ENTITY_EXPANSION)
+     assert_equal("\na\na a\n<\n", doc.root.children.first.value)
+@@ -87,6 +129,15 @@
+     assert_raise(REXML::ParseException) do
+       REXML::Document.new(XML_WITH_NESTED_PARAMETER_ENTITY)
+     end
++
++    assert_raise(REXML::ParseException) do
++      REXML::Document.new(XML_WITH_NESTED_EMPTY_PARAMETER_ENTITY)
++    end
++    REXML::Document.entity_expansion_limit = 100
++    assert_equal(100, REXML::Document.entity_expansion_limit)
++    assert_raise(REXML::ParseException) do
++      REXML::Document.new(XML_WITH_NESTED_EMPTY_PARAMETER_ENTITY)
++    end
+   ensure
+     REXML::Document.entity_expansion_limit = 10000
+   end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch
new file mode 100644
index 000000000..c9ec06223
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2015-1855.patch
@@ -0,0 +1,270 @@
+Fix CVE-2015-1855:
+
+https://bugs.ruby-lang.org/issues/9644
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1855
+https://security-tracker.debian.org/tracker/CVE-2015-1855
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+The patch was intended for 1.8.7-p358. To apply it to 1.8.7-p374,
+surrounding text of hunk #1 are changed.
+
+Description: Fix OpenSSL hostname verification
+ Backported from the Ruby 2.0 branch. See
+ https://bugs.ruby-lang.org/issues/9644 for details.
+Origin: upstream, 
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=50292
+Forwarded: not-needed
+Last-Update: 2015-04-26
+Reviewed-by: Antonio Terceiro <address@hidden>
+
+--- a/ext/openssl/lib/openssl/ssl-internal.rb
++++ b/ext/openssl/lib/openssl/ssl-internal.rb
+@@ -96,8 +96,7 @@ module OpenSSL
+           case san.tag
+           when 2 # dNSName in GeneralName (RFC5280)
+             should_verify_common_name = false
+-            reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+")
+-            return true if /\A#{reg}\z/i =~ hostname
++            return true if verify_hostname(hostname, san.value)
+           when 7 # iPAddress in GeneralName (RFC5280)
+             should_verify_common_name = false
+             # follows GENERAL_NAME_print() in x509v3/v3_alt.c
+@@ -112,8 +111,7 @@ module OpenSSL
+       if should_verify_common_name
+         cert.subject.to_a.each{|oid, value|
+           if oid == "CN"
+-            reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
+-            return true if /\A#{reg}\z/i =~ hostname
++            return true if verify_hostname(hostname, value)
+           end
+         }
+       end
+@@ -121,11 +119,67 @@ module OpenSSL
+     end
+     module_function :verify_certificate_identity
+ 
++    def verify_hostname(hostname, san) # :nodoc:
++      # RFC 5280, IA5String is limited to the set of ASCII characters
++      return false if san =~ /[\x80-\xff]/
++      return false if hostname =~ /[\x80-\xff]/
++
++      # See RFC 6125, section 6.4.1
++      # Matching is case-insensitive.
++      san_parts = san.downcase.split(".")
++
++      # TODO: this behavior should probably be more strict
++      return san == hostname if san_parts.size < 2
++
++      # Matching is case-insensitive.
++      host_parts = hostname.downcase.split(".")
++
++      # RFC 6125, section 6.4.3, subitem 2.
++      # If the wildcard character is the only character of the left-most
++      # label in the presented identifier, the client SHOULD NOT compare
++      # against anything but the left-most label of the reference
++      # identifier (e.g., *.example.com would match foo.example.com but
++      # not bar.foo.example.com or example.com).
++      return false unless san_parts.size == host_parts.size
++
++      # RFC 6125, section 6.4.3, subitem 1.
++      # The client SHOULD NOT attempt to match a presented identifier in
++      # which the wildcard character comprises a label other than the
++      # left-most label (e.g., do not match bar.*.example.net).
++      return false unless verify_wildcard(host_parts.shift, san_parts.shift)
++
++      san_parts.join(".") == host_parts.join(".")
++    end
++    module_function :verify_hostname
++
++    def verify_wildcard(domain_component, san_component) # :nodoc:
++      parts = san_component.split("*", -1)
++
++      return false if parts.size > 2
++      return san_component == domain_component if parts.size == 1
++
++      # RFC 6125, section 6.4.3, subitem 3.
++      # The client SHOULD NOT attempt to match a presented identifier
++      # where the wildcard character is embedded within an A-label or
++      # U-label of an internationalized domain name.
++      return false if domain_component.start_with?("xn--") && san_component 
!= "*"
++
++      parts[0].length + parts[1].length < domain_component.length &&
++      domain_component.start_with?(parts[0]) &&
++      domain_component.end_with?(parts[1])
++    end
++    module_function :verify_wildcard
++
+     class SSLSocket
+       include Buffering
+       include SocketForwarder
+       include Nonblock
+ 
++      ##
++      # Perform hostname verification after an SSL connection is established
++      #
++      # This method MUST be called after calling #connect to ensure that the
++      # hostname of a remote peer has been verified.
+       def post_connection_check(hostname)
+         unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+           raise SSLError, "hostname was not match with the server certificate"
+--- a/test/openssl/test_ssl.rb
++++ b/test/openssl/test_ssl.rb
+@@ -560,6 +560,156 @@ class OpenSSL::TestSSL < Test::Unit::Tes
+     end
+   end
+ 
++  def test_verify_hostname
++    assert_equal(true,  OpenSSL::SSL.verify_hostname("www.example.com", 
"*.example.com"))
++    assert_equal(false, 
OpenSSL::SSL.verify_hostname("www.subdomain.example.com", "*.example.com"))
++  end
++
++  def test_verify_wildcard
++    assert_equal(false, OpenSSL::SSL.verify_wildcard("foo", "x*"))
++    assert_equal(true,  OpenSSL::SSL.verify_wildcard("foo", "foo"))
++    assert_equal(true,  OpenSSL::SSL.verify_wildcard("foo", "f*"))
++    assert_equal(true,  OpenSSL::SSL.verify_wildcard("foo", "*"))
++    assert_equal(false, OpenSSL::SSL.verify_wildcard("abc*bcd", "abcd"))
++    assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "x*"))
++    assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", 
"*--qdk4b9b"))
++    assert_equal(true,  OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", 
"xn--qdk4b9b"))
++  end
++
++  # Comments in this test is excerpted from 
http://tools.ietf.org/html/rfc6125#page-27
++  def test_post_connection_check_wildcard_san
++    # case-insensitive ASCII comparison
++    # RFC 6125, section 6.4.1
++    #
++    # "..matching of the reference identifier against the presented identifier
++    # is performed by comparing the set of domain name labels using a
++    # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g.,
++    # "WWW.Example.Com" would be lower-cased to "www.example.com" for
++    # comparison purposes)
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*.example.com'), 'www.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*.Example.COM'), 'www.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*.example.com'), 'WWW.Example.COM'))
++    # 1.  The client SHOULD NOT attempt to match a presented identifier in
++    #     which the wildcard character comprises a label other than the
++    #     left-most label (e.g., do not match bar.*.example.net).
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:www.*.com'), 'www.example.com'))
++    # 2.  If the wildcard character is the only character of the left-most
++    #     label in the presented identifier, the client SHOULD NOT compare
++    #     against anything but the left-most label of the reference
++    #     identifier (e.g., *.example.com would match foo.example.com but
++    #     not bar.foo.example.com or example.com).
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*.example.com'), 'foo.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*.example.com'), 'bar.foo.example.com'))
++    # 3.  The client MAY match a presented identifier in which the wildcard
++    #     character is not the only character of the label (e.g.,
++    #     baz*.example.net and *baz.example.net and b*z.example.net would
++    #     be taken to match baz1.example.net and foobaz.example.net and
++    #     buzz.example.net, respectively).  ...
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com'))
++    # Section 6.4.3 of RFC6125 states that client should NOT match identifier
++    # where wildcard is other than left-most label.
++    #
++    # Also implicitly mentions the wildcard character only in singular form,
++    # and discourages matching against more than one wildcard.
++    #
++    # See RFC 6125, section 7.2, subitem 2.
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*b*.example.com'), 'abc.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*b*.example.com'), 'ab.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:*b*.example.com'), 'bc.example.com'))
++    #                                ...  However, the client SHOULD NOT
++    #   attempt to match a presented identifier where the wildcard
++    #   character is embedded within an A-label or U-label [IDNA-DEFS] of
++    #   an internationalized domain name [IDNA-PROTO].
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:xn*.example.com'), 'xn1ca.example.com'))
++    # part of A-label
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:xn--*.example.com'), 'xn--1ca.example.com'))
++    # part of U-label
++    # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed
++    # regardless of wildcard.
++    #
++    # See Section 7.2 of RFC 5280:
++    #   IA5String is limited to the set of ASCII characters.
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_san('DNS:े*.example.com'), 'े1.example.com'))
++  end
++
++  def test_post_connection_check_wildcard_cn
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*.example.com'), 'www.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*.Example.COM'), 'www.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*.example.com'), 'WWW.Example.COM'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('www.*.com'), 'www.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*.example.com'), 'foo.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*.example.com'), 'bar.foo.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('baz*.example.com'), 'baz1.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*baz.example.com'), 'foobaz.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('b*z.example.com'), 'buzz.example.com'))
++    # Section 6.4.3 of RFC6125 states that client should NOT match identifier
++    # where wildcard is other than left-most label.
++    #
++    # Also implicitly mentions the wildcard character only in singular form,
++    # and discourages matching against more than one wildcard.
++    #
++    # See RFC 6125, section 7.2, subitem 2.
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*b*.example.com'), 'abc.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*b*.example.com'), 'ab.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('*b*.example.com'), 'bc.example.com'))
++    assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('xn*.example.com'), 'xn1ca.example.com'))
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('xn--*.example.com'), 'xn--1ca.example.com'))
++    # part of U-label
++    # Subject in RFC5280 states case-insensitive ASCII comparison.
++    #
++    # See Section 7.2 of RFC 5280:
++    #   IA5String is limited to the set of ASCII characters.
++    assert_equal(false, OpenSSL::SSL.verify_certificate_identity(
++      create_cert_with_name('े*.example.com'), 'े1.example.com'))
++  end
++
++  def create_cert_with_san(san)
++    ef = OpenSSL::X509::ExtensionFactory.new
++    cert = OpenSSL::X509::Certificate.new
++    cert.subject = OpenSSL::X509::Name.parse("/DC=some/DC=site/CN=Some Site")
++    ext = ef.create_ext('subjectAltName', san)
++    cert.add_extension(ext)
++    cert
++  end
++
++  def create_cert_with_name(name)
++    cert = OpenSSL::X509::Certificate.new
++    cert.subject = OpenSSL::X509::Name.new([['DC', 'some'], ['DC', 'site'], 
['CN', name]])
++    cert
++  end
++
++
+ end
+ 
+ end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch
new file mode 100644
index 000000000..aba4d356a
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-0898.patch
@@ -0,0 +1,110 @@
+Fix CVE-2017-0898:
+
+https://www.ruby-lang.org/en/news/2017/09/14/sprintf-buffer-underrun-cve-2017-0898/
+https://bugs.ruby-lang.org/issues/13499
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-0898
+https://security-tracker.debian.org/tracker/CVE-2017-0898
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Description: security fix for CVE-2017-0898
+
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=875936
+Reviewed-By: anarcat
+Last-Update: 2017-09-26
+Origin: OpenBSD, 
https://raw.githubusercontent.com/openbsd/ports/master/lang/ruby/1.8/patches/patch-sprintf_c
+
+$OpenBSD: patch-sprintf_c,v 1.1 2017/09/16 22:54:58 jeremy Exp $
+
+--- a/sprintf.c
++++ b/sprintf.c
+@@ -728,6 +728,8 @@ rb_str_format(argc, argv, fmt)
+ #if defined(_WIN32) && !defined(__BORLANDC__)
+               if (isnan(fval) || isinf(fval)) {
+                   const char *expr;
++                  int elen;
++                  char sign = '\0';
+ 
+                   if  (isnan(fval)) {
+                       expr = "NaN";
+@@ -736,51 +738,40 @@ rb_str_format(argc, argv, fmt)
+                       expr = "Inf";
+                   }
+                   need = strlen(expr);
+-                  if ((!isnan(fval) && fval < 0.0) || (flags & FPLUS))
+-                      need++;
+-                  else if (flags & FSPACE)
+-                      need++;
++                  elen = need;
++                  i = 0;
++                  if (!isnan(fval) && fval < 0.0)
++                      sign = '-';
++                  else if (flags & (FPLUS|FSPACE))
++                      sign = (flags & FPLUS) ? '+' : ' ';
++                  if (sign)
++                      ++need;
+                   if ((flags & FWIDTH) && need < width)
+                       need = width;
+ 
+-                  CHECK(need);
+-                  sprintf(&buf[blen], "%*s", need, "");
++#define FILL(c, l) do { \
++    if ((l) <= 0) break;\
++    CHECK(l);\
++    FILL_(c, l);\
++} while (0)
++
++#define FILL_(c, l) do { \
++    memset(&buf[blen], (c), (l));\
++    blen += (l);\
++} while (0)
++
++                  
++                  FILL(' ', need);
+                   if (flags & FMINUS) {
+-                      if (!isnan(fval) && fval < 0.0)
+-                          buf[blen++] = '-';
+-                      else if (flags & FPLUS)
+-                          buf[blen++] = '+';
+-                      else if (flags & FSPACE)
+-                          blen++;
+-                      strncpy(&buf[blen], expr, strlen(expr));
+-                  }
+-                  else if (flags & FZERO) {
+-                      if (!isnan(fval) && fval < 0.0) {
+-                          buf[blen++] = '-';
+-                          need--;
+-                      }
+-                      else if (flags & FPLUS) {
+-                          buf[blen++] = '+';
+-                          need--;
+-                      }
+-                      else if (flags & FSPACE) {
+-                          blen++;
+-                          need--;
+-                      }
+-                      while (need-- - strlen(expr) > 0) {
+-                          buf[blen++] = '0';
+-                      }
+-                      strncpy(&buf[blen], expr, strlen(expr));
++                      if (sign)
++                          buf[blen - need--] = sign;
++                      memcpy(&buf[blen - need], expr, elen);
+                   }
+                   else {
+-                      if (!isnan(fval) && fval < 0.0)
+-                          buf[blen + need - strlen(expr) - 1] = '-';
+-                      else if (flags & FPLUS)
+-                          buf[blen + need - strlen(expr) - 1] = '+';
+-                      strncpy(&buf[blen + need - strlen(expr)], expr,
+-                              strlen(expr));
++                      if (sign)
++                          buf[blen - elen - 1] = sign;
++                      memcpy(&buf[blen - elen], expr, elen);
+                   }
+-                  blen += strlen(&buf[blen]);
+                   break;
+               }
+ #endif        /* defined(_WIN32) && !defined(__BORLANDC__) */
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch
new file mode 100644
index 000000000..4f13f94ee
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-10784.patch
@@ -0,0 +1,99 @@
+Fix CVE-2017-10784:
+
+https://www.ruby-lang.org/en/news/2017/09/14/webrick-basic-auth-escape-sequence-injection-cve-2017-10784/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-10784
+https://security-tracker.debian.org/tracker/CVE-2017-10784
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From 6617c41292b7d1e097abb8fdb0cab9ddd83c77e7 Mon Sep 17 00:00:00 2001
+From: mame <address@hidden>
+Date: Thu, 14 Sep 2017 11:16:23 +0000
+Subject: [PATCH] lib/webrick/log.rb: sanitize any type of logs
+
+It had failed to sanitize some type of exception messages.  Reported and
+patched by Yusuke Endoh (mame) at https://hackerone.com/reports/223363
+
+Patch modified to backport to Ruby 1.8.7.358 for the Debian LTS
+project by anarcat.
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ lib/webrick/httpstatus.rb     |  4 ----
+ lib/webrick/log.rb            |  4 ++--
+ test/webrick/test_httpauth.rb | 36 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 38 insertions(+), 6 deletions(-)
+
+--- a/lib/webrick/httpstatus.rb
++++ b/lib/webrick/httpstatus.rb
+@@ -13,10 +13,6 @@ module WEBrick
+   module HTTPStatus
+ 
+     class Status      < StandardError
+-      def initialize(*args)
+-        args[0] = AccessLog.escape(args[0]) unless args.empty?
+-        super(*args)
+-      end
+       class << self
+         attr_reader :code, :reason_phrase
+       end
+--- a/lib/webrick/log.rb
++++ b/lib/webrick/log.rb
+@@ -61,10 +61,10 @@ module WEBrick
+ 
+     def format(arg)
+       str = if arg.is_a?(Exception)
+-        "#{arg.class}: #{arg.message}\n\t" <<
++        "#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" <<
+         arg.backtrace.join("\n\t") << "\n"
+       elsif arg.respond_to?(:to_str)
+-        arg.to_str
++        AccessLog.escape(arg.to_str)
+       else
+         arg.inspect
+       end
+--- a/test/webrick/test_httpauth.rb
++++ b/test/webrick/test_httpauth.rb
+@@ -79,4 +79,40 @@ class TestWEBrickHTTPAuth < Test::Unit::
+     }
+     tmpfile.close(true)
+   end
++
++  def test_bad_username_with_control_characters
++    log_tester = lambda {|log, access_log|
++      assert_equal(2, log.length)
++      assert_match(/ERROR Basic WEBrick's realm: foo\\ebar: the user is not 
allowed./, log[0])
++      assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[1])
++    }
++    TestWEBrick.start_httpserver{|server, addr, port, log|
++      realm = "WEBrick's realm"
++      path = "/basic_auth"
++
++      Tempfile.open("test_webrick_auth") { |tmpfile|
++        tmpfile.close
++        tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
++        tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
++        tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
++        tmp_pass.flush
++
++        htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
++        users = []
++        htpasswd.each{|user, pass| users << user }
++        server.mount_proc(path){|req, res|
++          auth = WEBrick::HTTPAuth::BasicAuth.new(
++            :Realm => realm, :UserDB => htpasswd,
++            :Logger => server.logger
++          )
++          auth.authenticate(req, res)
++          res.body = "hoge"
++        }
++        http = Net::HTTP.new(addr, port)
++        g = Net::HTTP::Get.new(path)
++        g.basic_auth("foo\ebar", "passwd")
++        http.request(g){|res| assert_not_equal("hoge", res.body, log.call) }
++      }
++    }
++  end
+ end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch
new file mode 100644
index 000000000..5882946cb
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17405.patch
@@ -0,0 +1,62 @@
+Fix CVE-2017-17405:
+
+https://www.ruby-lang.org/en/news/2017/12/14/net-ftp-command-injection-cve-2017-17405/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17405
+https://security-tracker.debian.org/tracker/CVE-2017-17405
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From: =?utf-8?q?Guido_G=C3=BCnther?= <address@hidden>
+Date: Sun, 24 Dec 2017 16:16:29 +0100
+Subject: CVE-2017-17405: command injection attacks via Net::FTP
+
+---
+ lib/net/ftp.rb | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb
+index 369aba8..bfa6c4b 100644
+--- a/lib/net/ftp.rb
++++ b/lib/net/ftp.rb
+@@ -494,10 +494,10 @@ module Net
+                     blocksize = DEFAULT_BLOCKSIZE, &block) # :yield: data
+       if @resume
+       rest_offset = File.size?(localfile)
+-      f = open(localfile, "a")
++      f = File.open(localfile, "a")
+       else
+       rest_offset = nil
+-      f = open(localfile, "w")
++      f = File.open(localfile, "w")
+       end
+       begin
+       f.binmode
+@@ -516,7 +516,7 @@ module Net
+     # line at a time.
+     #
+     def gettextfile(remotefile, localfile = File.basename(remotefile), 
&block) # :yield: line
+-      f = open(localfile, "w")
++      f = File.open(localfile, "w")
+       begin
+       retrlines("RETR " + remotefile) do |line|
+         f.puts(line)
+@@ -556,7 +556,7 @@ module Net
+       else
+       rest_offset = nil
+       end
+-      f = open(localfile)
++      f = File.open(localfile)
+       begin
+       f.binmode
+       storbinary("STOR " + remotefile, f, blocksize, rest_offset, &block)
+@@ -571,7 +571,7 @@ module Net
+     # passing in the transmitted data one line at a time.
+     #
+     def puttextfile(localfile, remotefile = File.basename(localfile), &block) 
# :yield: line
+-      f = open(localfile)
++      f = File.open(localfile)
+       begin
+       storlines("STOR " + remotefile, f, &block)
+       ensure
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch
new file mode 100644
index 000000000..2e5a3a776
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17742-pre.patch
@@ -0,0 +1,161 @@
+Prepare to fix CVE-2017-17742:
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Index: ruby1.9.1/test/webrick/test_httpresponse.rb
+===================================================================
+--- /dev/null
++++ ruby1.9.1/test/webrick/test_httpresponse.rb
+@@ -0,0 +1,150 @@
++require "webrick"
++require "minitest/autorun"
++require "stringio"
++
++module WEBrick
++  class TestHTTPResponse < MiniTest::Unit::TestCase
++    class FakeLogger
++      attr_reader :messages
++
++      def initialize
++        @messages = []
++      end
++
++      def warn msg
++        @messages << msg
++      end
++    end
++
++    attr_reader :config, :logger, :res
++
++    def setup
++      super
++      @logger          = FakeLogger.new
++      @config          = Config::HTTP
++      @config[:Logger] = logger
++      @res             = HTTPResponse.new config
++      @res.keep_alive  = true
++    end
++
++    def test_304_does_not_log_warning
++      res.status      = 304
++      res.setup_header
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_204_does_not_log_warning
++      res.status      = 204
++      res.setup_header
++
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_1xx_does_not_log_warnings
++      res.status      = 105
++      res.setup_header
++
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_io
++      IO.pipe {|body_r, body_w|
++        body_w.write 'hello'
++        body_w.close
++
++        @res.body = body_r
++
++        IO.pipe {|r, w|
++
++          @res.send_body w
++
++          w.close
++
++          assert_equal 'hello', r.read
++        }
++      }
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_string
++      @res.body = 'hello'
++
++      IO.pipe {|r, w|
++        @res.send_body w
++
++        w.close
++
++        assert_equal 'hello', r.read
++      }
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_string_io
++      @res.body = StringIO.new 'hello'
++
++      IO.pipe {|r, w|
++        @res.send_body w
++
++        w.close
++
++        assert_equal 'hello', r.read
++      }
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_io_chunked
++      @res.chunked = true
++
++      IO.pipe {|body_r, body_w|
++
++        body_w.write 'hello'
++        body_w.close
++
++        @res.body = body_r
++
++        IO.pipe {|r, w|
++          @res.send_body w
++
++          w.close
++
++          r.binmode
++          assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
++        }
++      }
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_string_chunked
++      @res.chunked = true
++
++      @res.body = 'hello'
++
++      IO.pipe {|r, w|
++        @res.send_body w
++
++        w.close
++
++        r.binmode
++        assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
++      }
++      assert_equal 0, logger.messages.length
++    end
++
++    def test_send_body_string_io_chunked
++      @res.chunked = true
++
++      @res.body = StringIO.new 'hello'
++
++      IO.pipe {|r, w|
++        @res.send_body w
++
++        w.close
++
++        r.binmode
++        assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
++      }
++      assert_equal 0, logger.messages.length
++    end
++  end
++end
++
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch
new file mode 100644
index 000000000..0c15073c8
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17742.patch
@@ -0,0 +1,132 @@
+Fix CVE-2017-17742:
+
+https://www.ruby-lang.org/en/news/2018/03/28/http-response-splitting-in-webrick-cve-2017-17742/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17742
+https://security-tracker.debian.org/tracker/CVE-2017-17742
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From bbda1a027475bf7ce5e1a9583a7b55d0be71c8fe Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:50:27 +0000
+Subject: [PATCH 3/3] merge revision(s) 62968:
+
+       webrick: prevent response splitting and header injection
+
+       Original patch by tenderlove (with minor style adjustments).
+
+       * lib/webrick/httpresponse.rb (send_header): call check_header
+         (check_header): raise on embedded CRLF in header value
+       * test/webrick/test_httpresponse.rb
+         (test_prevent_response_splitting_headers): new test
+       * (test_prevent_response_splitting_cookie_headers): ditto
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog                         | 12 ++++++++++++
+ lib/webrick/httpresponse.rb       | 27 +++++++++++++++++++++++++--
+ test/webrick/test_httpresponse.rb | 22 ++++++++++++++++++++++
+ version.h                         |  2 +-
+ 4 files changed, 60 insertions(+), 3 deletions(-)
+
+Index: ruby1.8/lib/webrick/httpresponse.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httpresponse.rb
++++ ruby1.8/lib/webrick/httpresponse.rb
+@@ -16,6 +16,9 @@ require 'webrick/httpstatus'
+ 
+ module WEBrick
+   class HTTPResponse
++    class InvalidHeader < StandardError
++    end
++
+     BUFSIZE = 1024*4
+ 
+     attr_reader :http_version, :status, :header
+@@ -171,14 +174,19 @@ module WEBrick
+         data = status_line()
+         @header.each{|key, value|
+           tmp = key.gsub(/\bwww|^te$|\b\w/){|s| s.upcase }
+-          data << "#{tmp}: #{value}" << CRLF
++          data << "#{tmp}: #{check_header(value)}" << CRLF
+         }
+         @cookies.each{|cookie|
+-          data << "Set-Cookie: " << cookie.to_s << CRLF
++          data << "Set-Cookie: " << check_header(cookie.to_s) << CRLF
+         }
+         data << CRLF
+         _write_data(socket, data)
+       end
++    rescue InvalidHeader => e
++      @header.clear
++      @cookies.clear
++      set_error e
++      retry
+     end
+ 
+     def send_body(socket) # :nodoc:
+@@ -225,6 +233,22 @@ module WEBrick
+         host, port = @config[:ServerName], @config[:Port]
+       end
+ 
++      error_body(backtrace, ex, host, port)
++    end
++
++    private
++
++    def check_header(header_value)
++      if header_value =~ /\r\n/
++        raise InvalidHeader
++      else
++        header_value
++      end
++    end
++
++    # :stopdoc:
++
++    def error_body(backtrace, ex, host, port)
+       @body = ''
+       @body << <<-_end_of_html_
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+Index: ruby1.8/test/webrick/test_httpresponse.rb
+===================================================================
+--- ruby1.8.orig/test/webrick/test_httpresponse.rb
++++ ruby1.8/test/webrick/test_httpresponse.rb
+@@ -1,6 +1,7 @@
+ require "webrick"
+ require "minitest/autorun"
+ require "stringio"
++require "net/http"
+ 
+ module WEBrick
+   class TestHTTPResponse < MiniTest::Unit::TestCase
+@@ -27,6 +28,27 @@ module WEBrick
+       @res.keep_alive  = true
+     end
+ 
++    def test_prevent_response_splitting_headers
++      res['X-header'] = "malicious\r\nCookie: hack"
++      io = StringIO.new
++      res.send_response io
++      io.rewind
++      res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
++      assert_equal '500', res.code
++      refute_match 'hack', io.string
++    end
++
++    def test_prevent_response_splitting_cookie_headers
++      user_input = "malicious\r\nCookie: hack"
++      res.cookies << WEBrick::Cookie.new('author', user_input)
++      io = StringIO.new
++      res.send_response io
++      io.rewind
++      res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
++      assert_equal '500', res.code
++      refute_match 'hack', io.string
++    end
++
+     def test_304_does_not_log_warning
+       res.status      = 304
+       res.setup_header
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch
new file mode 100644
index 000000000..d1faa3a4d
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2017-17790.patch
@@ -0,0 +1,32 @@
+Fix CVE-2017-17790:
+
+https://github.com/ruby/ruby/pull/1777
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17790
+https://security-tracker.debian.org/tracker/CVE-2017-17790
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From: =?utf-8?q?Guido_G=C3=BCnther?= <address@hidden>
+Date: Sun, 24 Dec 2017 16:19:08 +0100
+Subject: CVE-2017-17790: Fixed command injection in
+ Resolv::Hosts#lazy_initialize
+
+---
+ lib/resolv.rb | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/resolv.rb b/lib/resolv.rb
+index 5cc0313..417fe0c 100644
+--- a/lib/resolv.rb
++++ b/lib/resolv.rb
+@@ -186,7 +186,7 @@ class Resolv
+         unless @initialized
+           @name2addr = {}
+           @addr2name = {}
+-          open(@filename) {|f|
++          File.open(@filename) {|f|
+             f.each {|line|
+               line.sub!(/#.*/, '')
+               addr, hostname, *aliases = line.split(/\s+/)
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch
new file mode 100644
index 000000000..75705db68
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-6914.patch
@@ -0,0 +1,99 @@
+Fix CVE-2018-6914:
+
+https://www.ruby-lang.org/en/news/2018/03/28/unintentional-file-and-directory-creation-with-directory-traversal-cve-2018-6914/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6914
+https://security-tracker.debian.org/tracker/CVE-2018-6914
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Origin: backport, e9ddf2ba41a0bffe1047e33576affd48808c5d0b
+Reviewed-by: Santiago R.R <address@hidden>
+
+From e9ddf2ba41a0bffe1047e33576affd48808c5d0b Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:34:14 +0000
+Subject: [PATCH 2/4] merge revision(s) 62990:
+
+       Ignore file separator from tmpfile/tmpdir name.
+
+       From: SHIBATA Hiroshi <address@hidden>
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog             |  4 ++++
+ lib/tmpdir.rb         |  2 ++
+ test/test_tempfile.rb | 28 +++++++++++++++++++++++++++-
+ test/test_tmpdir.rb   | 34 ++++++++++++++++++++++++++++++++++
+ version.h             |  2 +-
+ 5 files changed, 68 insertions(+), 2 deletions(-)
+
+Index: ruby1.8/lib/tmpdir.rb
+===================================================================
+--- ruby1.8.orig/lib/tmpdir.rb
++++ ruby1.8/lib/tmpdir.rb
+@@ -110,6 +110,8 @@ class Dir
+     else
+       raise ArgumentError, "unexpected prefix_suffix: 
#{prefix_suffix.inspect}"
+     end
++    prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
++    suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
+     tmpdir ||= Dir.tmpdir
+     t = Time.now.strftime("%Y%m%d")
+     n = nil
+Index: ruby1.8/test/test_tempfile.rb
+===================================================================
+--- /dev/null
++++ ruby1.8/test/test_tempfile.rb
+@@ -0,0 +1,37 @@
++require 'test/unit'
++require 'tempfile'
++require './ruby/envutil'
++
++class TestTempfile < Test::Unit::TestCase
++  def initialize(*)
++    super
++    @tempfile = nil
++  end
++
++  TRAVERSAL_PATH = Array.new(Dir.pwd.split('/').count, '..').join('/') + 
Dir.pwd + '/'
++
++  def test_open_traversal_dir
++    expect = Dir.glob(TRAVERSAL_PATH + '*').count
++    t = Tempfile.open([TRAVERSAL_PATH, 'foo'])
++    actual = Dir.glob(TRAVERSAL_PATH + '*').count
++    assert_equal expect, actual
++  ensure
++    t.close!
++  end
++
++  def test_new_traversal_dir
++    expect = Dir.glob(TRAVERSAL_PATH + '*').count
++    t = Tempfile.new(TRAVERSAL_PATH + 'foo')
++    actual = Dir.glob(TRAVERSAL_PATH + '*').count
++    assert_equal expect, actual
++  ensure
++    t.close!
++  end
++
++  def test_create_traversal_dir
++    expect = Dir.glob(TRAVERSAL_PATH + '*').count
++    Tempfile.create(TRAVERSAL_PATH + 'foo')
++    actual = Dir.glob(TRAVERSAL_PATH + '*').count
++    assert_equal expect, actual
++  end
++end
+Index: ruby1.8/lib/tempfile.rb
+===================================================================
+--- ruby1.8.orig/lib/tempfile.rb
++++ ruby1.8/lib/tempfile.rb
+@@ -79,6 +79,8 @@ class Tempfile < DelegateClass(File)
+     else
+       prefix, suffix = basename, ''
+     end
++    prefix = prefix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
++    suffix &&= suffix.delete("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")
+  
+     t = Time.now.strftime("%Y%m%d")
+     path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}"
diff --git 
a/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch
new file mode 100644
index 000000000..76d74e48e
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch
@@ -0,0 +1,366 @@
+Prepare to fix CVE-2018-8777 and CVE-2017-17742:
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From 19cb3fa9e0621004a9dc08e90884c512c75dac57 Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:44:20 +0000
+Subject: [PATCH 1/3] merge revision(s) 60584,62954-62959,63008:
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+       webrick: support Proc objects as body responses
+
+       * lib/webrick/httpresponse.rb (send_body): call send_body_proc
+         (send_body_proc): new method
+         (class ChunkedWrapper): new class
+
+       * test/webrick/test_httpresponse.rb (test_send_body_proc): new test
+         (test_send_body_proc_chunked): ditto
+         [Feature #855]
+
+       webrick: favor .write over << method
+
+       This will make the next change to use IO.copy_stream
+       easier-to-read.  When we can drop Ruby 2.4 support in a few
+       years, this will allow us to use writev(2) with multiple
+       arguments for headers and chunked responses.
+
+       * lib/webrick/cgi.rb (write): new wrapper method
+         lib/webrick/httpresponse.rb: (send_header): use socket.write
+         (send_body_io): ditto
+         (send_body_string): ditto
+         (send_body_proc): ditto
+         (_write_data): ditto
+         (ChunkedWrapper#write): ditto
+         (_send_file): ditto
+       ------------------------------------------------------------------------
+       r62954 | normal | 2018-03-28 17:05:52 +0900 (ौओख, 28 3 2018) | 14 lines
+
+       webrick/httpresponse: IO.copy_stream for regular files
+
+       Remove the redundant _send_file method since its functionality
+       is unnecessary with IO.copy_stream.  IO.copy_stream also allows
+       the use of sendfile under some OSes to speed up copies to
+       non-TLS sockets.
+
+       Testing with "curl >/dev/null" and "ruby -run -e httpd" to
+       read a 1G file over Linux loopback reveals a reduction from
+       around ~0.770 to ~0.490 seconds on the client side.
+
+       * lib/webrick/httpresponse.rb (send_body_io): use IO.copy_stream
+         (_send_file): remove
+         [Feature #14237]
+       ------------------------------------------------------------------------
+       r62955 | normal | 2018-03-28 17:05:57 +0900 (ौओख, 28 3 2018) | 10 lines
+
+       webrick: use IO.copy_stream for single range response
+
+       This is also compatible with range responses generated
+       by Rack::File (tested with rack 2.0.3).
+
+       * lib/webrick/httpresponse.rb (send_body_io): use Content-Range
+       * lib/webrick/httpservlet/filehandler.rb (make_partial_content):
+         use File object for the single range case
+       * test/webrick/test_filehandler.rb (get_res_body): use send_body
+         to test result
+       ------------------------------------------------------------------------
+       r62956 | normal | 2018-03-28 17:06:02 +0900 (ौओख, 28 3 2018) | 7 lines
+
+       test/webrick/test_filehandler.rb: stricter multipart range test
+
+       We need to ensure we generate compatibile output in
+       the face of future changes
+
+       * test/webrick/test_filehandler.rb (test_make_partial_content):
+         check response body
+       ------------------------------------------------------------------------
+       r62957 | normal | 2018-03-28 17:06:08 +0900 (ौओख, 28 3 2018) | 8 lines
+
+       webrick: quiet warning for multi-part ranges
+
+       Content-Length is ignored by WEBrick::HTTPResponse even if we
+       calculate it, so instead we chunk responses to HTTP/1.1 clients
+       and terminate HTTP/1.0 connections.
+
+       * lib/webrick/httpservlet/filehandler.rb (make_partial_content):
+         quiet warning
+       ------------------------------------------------------------------------
+       r62958 | normal | 2018-03-28 17:06:13 +0900 (ौओख, 28 3 2018) | 7 lines
+
+       webrick/httpresponse: make ChunkedWrapper copy_stream-compatible
+
+       The .write method needs to return the number of bytes written
+       to avoid confusing IO.copy_stream.
+
+       * lib/webrick/httpresponse.rb (ChunkedWrapper#write): return bytes 
written
+         (ChunkedWrapper#<<): return self
+       ------------------------------------------------------------------------
+       r62959 | normal | 2018-03-28 17:06:18 +0900 (ौओख, 28 3 2018) | 9 lines
+
+       webrick: use IO.copy_stream for multipart response
+
+       Use the new Proc response body feature to generate a multipart
+       range response dynamically.  We use a flat array to minimize
+       object overhead as much as possible; as many ranges may fit
+       into an HTTP request header.
+
+       * lib/webrick/httpservlet/filehandler.rb (multipart_body): new method
+         (make_partial_content): use multipart_body
+
+       get rid of test error/failure on Windows introduced at r62955
+
+       * lib/webrick/httpresponse.rb (send_body_io): use seek if 
NotImplementedError
+         is raised in IO.copy_stream with offset.
+
+       * lib/webrick/httpservlet/filehandler.rb (multipart_body): ditto.
+
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog                              | 98 ++++++++++++++++++++++++++++++++++
+ lib/webrick/httpresponse.rb            | 68 ++++++++++++++++-------
+ lib/webrick/httpservlet/filehandler.rb | 65 ++++++++++++++--------
+ test/webrick/test_filehandler.rb       | 31 +++++++----
+ test/webrick/test_httpresponse.rb      | 33 ++++++++++++
+ version.h                              |  2 +-
+ 6 files changed, 244 insertions(+), 53 deletions(-)
+
+Index: ruby1.8/lib/webrick/httpresponse.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httpresponse.rb
++++ ruby1.8/lib/webrick/httpresponse.rb
+@@ -181,10 +181,13 @@ module WEBrick
+       end
+     end
+ 
+-    def send_body(socket)
+-      case @body
+-      when IO then send_body_io(socket)
+-      else send_body_string(socket)
++    def send_body(socket) # :nodoc:
++      if @body.respond_to? :readpartial then
++        send_body_io(socket)
++      elsif @body.respond_to?(:call) then
++        send_body_proc(socket)
++      else
++        send_body_string(socket)
+       end
+     end
+ 
+@@ -268,9 +271,20 @@ module WEBrick
+           end
+           _write_data(socket, "0#{CRLF}#{CRLF}")
+         else
+-          size = @header['content-length'].to_i
+-          _send_file(socket, @body, 0, size)
+-          @sent_size = size
++          if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ @header['content-range']
++            offset = $1.to_i
++            size = $2.to_i - offset + 1
++          else
++            offset = nil
++            size = @header['content-length']
++            size = size.to_i if size
++          end
++          begin
++            @sent_size = IO.copy_stream(@body, socket, size, offset)
++          rescue NotImplementedError
++            @body.seek(offset, IO::SEEK_SET)
++            @sent_size = IO.copy_stream(@body, socket, size)
++          end
+         end
+       ensure
+         @body.close
+@@ -299,24 +313,41 @@ module WEBrick
+       end
+     end
+ 
+-    def _send_file(output, input, offset, size)
+-      while offset > 0
+-        sz = BUFSIZE < offset ? BUFSIZE : offset
+-        buf = input.read(sz)
+-        offset -= buf.size
++    def send_body_proc(socket)
++      if @request_method == "HEAD"
++        # do nothing
++      elsif chunked?
++        @body.call(ChunkedWrapper.new(socket, self))
++        _write_data(socket, "0#{CRLF}#{CRLF}")
++      else
++        size = @header['content-length'].to_i
++        @body.call(socket)
++        @sent_size = size
+       end
++    end
+ 
+-      if size == 0
+-        while buf = input.read(BUFSIZE)
+-          _write_data(output, buf)
+-        end
+-      else
+-        while size > 0
+-          sz = BUFSIZE < size ? BUFSIZE : size
+-          buf = input.read(sz)
+-          _write_data(output, buf)
+-          size -= buf.size
+-        end
++    class ChunkedWrapper
++      def initialize(socket, resp)
++        @socket = socket
++        @resp = resp
++      end
++
++      def write(buf)
++        return 0 if buf.empty?
++        socket = @socket
++        @resp.instance_eval {
++          size = buf.bytesize
++          data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}"
++          _write_data(socket, data)
++          data.clear
++          @sent_size += size
++          size
++        }
++      end
++
++      def <<(*buf)
++        write(buf)
++        self
+       end
+     end
+ 
+Index: ruby1.8/lib/webrick/httpservlet/filehandler.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httpservlet/filehandler.rb
++++ ruby1.8/lib/webrick/httpservlet/filehandler.rb
+@@ -69,6 +69,35 @@ module WEBrick
+         return false
+       end
+ 
++      # returns a lambda for webrick/httpresponse.rb send_body_proc
++      def multipart_body(body, parts, boundary, mtype, filesize)
++        lambda do |socket|
++          begin
++            begin
++              first = parts.shift
++              last = parts.shift
++              socket.write(
++                "--#{boundary}#{CRLF}" \
++                "Content-Type: #{mtype}#{CRLF}" \
++                "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
++                "#{CRLF}"
++              )
++
++              begin
++                IO.copy_stream(body, socket, last - first + 1, first)
++              rescue NotImplementedError
++                body.seek(first, IO::SEEK_SET)
++                IO.copy_stream(body, socket, last - first + 1)
++              end
++              socket.write(CRLF)
++            end while parts[0]
++            socket.write("--#{boundary}--#{CRLF}")
++          ensure
++            body.close
++          end
++        end
++      end
++
+       def make_partial_content(req, res, filename, filesize)
+         mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
+         unless ranges = HTTPUtils::parse_range_header(req['range'])
+@@ -79,37 +108,27 @@ module WEBrick
+           if ranges.size > 1
+             time = Time.now
+             boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
+-            body = ''
+-            ranges.each{|range|
+-              first, last = prepare_range(range, filesize)
+-              next if first < 0
+-              io.pos = first
+-              content = io.read(last-first+1)
+-              body << "--" << boundary << CRLF
+-              body << "Content-Type: #{mtype}" << CRLF
+-              body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << 
CRLF
+-              body << CRLF
+-              body << content
+-              body << CRLF
++            parts = []
++            ranges.each {|range|
++              prange = prepare_range(range, filesize)
++              next if prange[0] < 0
++              parts.concat(prange)
+             }
+-            raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
+-            body << "--" << boundary << "--" << CRLF
++            raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
+             res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
+-            res.body = body
++            if req.http_version < '1.1'
++              res['connection'] = 'close'
++            else
++              res.chunked = true
++            end
++            res.body = multipart_body(io.dup, parts, boundary, mtype, 
filesize)
+           elsif range = ranges[0]
+             first, last = prepare_range(range, filesize)
+             raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
+-            if last == filesize - 1
+-              content = io.dup
+-              content.pos = first
+-            else
+-              io.pos = first
+-              content = io.read(last-first+1)
+-            end
+             res['content-type'] = mtype
+             res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
+             res['content-length'] = last - first + 1
+-            res.body = content
++            res.body = io.dup
+           else
+             raise HTTPStatus::BadRequest
+           end
+Index: ruby1.8/test/webrick/test_filehandler.rb
+===================================================================
+--- ruby1.8.orig/test/webrick/test_filehandler.rb
++++ ruby1.8/test/webrick/test_filehandler.rb
+@@ -14,7 +14,10 @@ class WEBrick::TestFileHandler < Test::U
+   end
+ 
+   def get_res_body(res)
+-    return res.body.read rescue res.body
++    sio = StringIO.new
++    sio.binmode
++    res.send_body(sio)
++    sio.string
+   end
+ 
+   def make_range_request(range_spec)
+@@ -66,6 +69,23 @@ class WEBrick::TestFileHandler < Test::U
+ 
+     res = make_range_response(filename, "bytes=0-0, -2")
+     assert_match(%r{^multipart/byteranges}, res["content-type"])
++    body = get_res_body(res)
++    boundary = /; boundary=(.+)/.match(res['content-type'])[1]
++    off = filesize - 2
++    last = filesize - 1
++
++    exp = "--#{boundary}\r\n" \
++          "Content-Type: text/plain\r\n" \
++          "Content-Range: bytes 0-0/#{filesize}\r\n" \
++          "\r\n" \
++          "#{IO.read(__FILE__, 1)}\r\n" \
++          "--#{boundary}\r\n" \
++          "Content-Type: text/plain\r\n" \
++          "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \
++          "\r\n" \
++          "#{IO.read(__FILE__, 2, off)}\r\n" \
++          "--#{boundary}--\r\n"
++    assert_equal exp, body
+   end
+ 
+   def test_filehandler
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch
new file mode 100644
index 000000000..5a279a4c7
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8777.patch
@@ -0,0 +1,394 @@
+Fix CVE-2018-8777:
+
+https://www.ruby-lang.org/en/news/2018/03/28/large-request-dos-in-webrick-cve-2018-8777/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8777
+https://security-tracker.debian.org/tracker/CVE-2018-8777
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From a45622669bb1ff18d3ee9b411128acd839c4263e Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:47:30 +0000
+Subject: [PATCH 2/3] merge revision(s) 62960-62965:
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+       webrick: use IO.copy_stream for multipart response
+
+       Use the new Proc response body feature to generate a multipart
+       range response dynamically.  We use a flat array to minimize
+       object overhead as much as possible; as many ranges may fit
+       into an HTTP request header.
+
+       * lib/webrick/httpservlet/filehandler.rb (multipart_body): new method
+         (make_partial_content): use multipart_body
+       ------------------------------------------------------------------------
+       r62960 | normal | 2018-03-28 17:06:23 +0900 (ौओख, 28 3 2018) | 13 lines
+
+       webrick/httprequest: limit request headers size
+
+       We use the same 112 KB limit started (AFAIK) by Mongrel, Thin,
+       and Puma to prevent malicious users from using up all the memory
+       with a single request.  This also limits the damage done by
+       excessive ranges in multipart Range: requests.
+
+       Due to the way we rely on IO#gets and the desire to keep
+       the code simple, the actual maximum header may be 4093 bytes
+       larger than 112 KB, but we're splitting hairs at that point.
+
+       * lib/webrick/httprequest.rb: define MAX_HEADER_LENGTH
+         (read_header): raise when headers exceed max length
+       ------------------------------------------------------------------------
+       r62961 | normal | 2018-03-28 17:06:28 +0900 (ौओख, 28 3 2018) | 9 lines
+
+       webrick/httpservlet/cgihandler: reduce memory use
+
+       WEBrick::HTTPRequest#body can be passed a block to process the
+       body in chunks.  Use this feature to avoid building a giant
+       string in memory.
+
+       * lib/webrick/httpservlet/cgihandler.rb (do_GET):
+         avoid reading entire request body into memory
+         (do_POST is aliased to do_GET, so it handles bodies)
+       ------------------------------------------------------------------------
+       r62962 | normal | 2018-03-28 17:06:34 +0900 (ौओख, 28 3 2018) | 7 lines
+
+       webrick/httprequest: raise correct exception
+
+       "BadRequest" alone does not resolve correctly, it is in the
+       HTTPStatus namespace.
+
+       * lib/webrick/httprequest.rb (read_chunked): use correct exception
+       * test/webrick/test_httpserver.rb (test_eof_in_chunk): new test
+       ------------------------------------------------------------------------
+       r62963 | normal | 2018-03-28 17:06:39 +0900 (ौओख, 28 3 2018) | 9 lines
+
+       webrick/httprequest: use InputBufferSize for chunked requests
+
+       While WEBrick::HTTPRequest#body provides a Proc interface
+       for streaming large request bodies, clients must not force
+       the server to use an excessively large chunk size.
+
+       * lib/webrick/httprequest.rb (read_chunk_size): limit each
+         read and block.call to :InputBufferSize in config.
+       * test/webrick/test_httpserver.rb (test_big_chunks): new test
+       ------------------------------------------------------------------------
+       r62964 | normal | 2018-03-28 17:06:44 +0900 (ौओख, 28 3 2018) | 9 lines
+
+       webrick: add test for Digest auth-int
+
+       No changes to the actual code, this is a new test for
+       a feature for which no tests existed.  I don't understand
+       the Digest authentication code well at all, but this is
+       necessary for the subsequent change.
+
+       * test/webrick/test_httpauth.rb (test_digest_auth_int): new test
+         (credentials_for_request): support bodies with POST
+       ------------------------------------------------------------------------
+       r62965 | normal | 2018-03-28 17:06:49 +0900 (ौओख, 28 3 2018) | 18 lines
+
+       webrick/httpauth/digestauth: stream req.body
+
+       WARNING! WARNING! WARNING!  LIKELY BROKEN CHANGE
+
+       Pass a proc to WEBrick::HTTPRequest#body to avoid reading a
+       potentially large request body into memory during
+       authentication.
+
+       WARNING! this will break apps completely which want to do
+       something with the body besides calculating the MD5 digest
+       of it.
+
+       Also, keep in mind that probably nobody uses "auth-int".
+       Servers such as Apache, lighttpd, nginx don't seem to
+       support it; nor does curl when using POST/PUT bodies;
+       and we didn't have tests for it until now...
+
+       * lib/webrick/httpauth/digestauth.rb (_authenticate): stream req.body
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog                             | 83 ++++++++++++++++++++++++++++++++
+ lib/webrick/httpauth/digestauth.rb    |  8 ++--
+ lib/webrick/httprequest.rb            | 23 ++++++---
+ lib/webrick/httpservlet/cgihandler.rb |  4 +-
+ test/webrick/test_httpauth.rb         | 90 ++++++++++++++++++++++++++++++++++-
+ test/webrick/test_httpserver.rb       | 67 ++++++++++++++++++++++++++
+ version.h                             |  2 +-
+ 7 files changed, 262 insertions(+), 15 deletions(-)
+
+Index: ruby1.8/lib/webrick/httpauth/digestauth.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httpauth/digestauth.rb
++++ ruby1.8/lib/webrick/httpauth/digestauth.rb
+@@ -176,9 +176,11 @@ module WEBrick
+           ha2 = hexdigest(req.request_method, auth_req['uri'])
+           ha2_res = hexdigest("", auth_req['uri'])
+         elsif auth_req['qop'] == "auth-int"
+-          ha2 = hexdigest(req.request_method, auth_req['uri'],
+-                          hexdigest(req.body))
+-          ha2_res = hexdigest("", auth_req['uri'], hexdigest(res.body))
++          body_digest = @h.new
++          req.body { |chunk| body_digest.update(chunk) }
++          body_digest = body_digest.hexdigest
++          ha2 = hexdigest(req.request_method, auth_req['uri'], body_digest)
++          ha2_res = hexdigest("", auth_req['uri'], body_digest)
+         end
+ 
+         if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
+Index: ruby1.8/lib/webrick/httprequest.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httprequest.rb
++++ ruby1.8/lib/webrick/httprequest.rb
+@@ -221,8 +221,17 @@ module WEBrick
+ 
+     private
+ 
++    MAX_URI_LENGTH = 2083 # :nodoc:
++
++    # same as Mongrel, Thin and Puma
++    MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
++
+     def read_request_line(socket)
+-      @request_line = read_line(socket) if socket
++      @request_line = read_line(socket, MAX_URI_LENGTH) if socket
++      @request_bytes = @request_line.bytesize
++      if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
++        raise HTTPStatus::RequestURITooLarge
++      end
+       @request_time = Time.now
+       raise HTTPStatus::EOFError unless @request_line
+       if /^(\S+)\s+(\S+?)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
+@@ -239,6 +248,9 @@ module WEBrick
+       if socket
+         while line = read_line(socket)
+           break if /\A(#{CRLF}|#{LF})\z/om =~ line
++          if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
++            raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
++          end
+           @raw_header << line
+         end
+       end
+@@ -304,17 +316,15 @@ module WEBrick
+     def read_chunked(socket, block)
+       chunk_size, = read_chunk_size(socket)
+       while chunk_size > 0
+-        data = ""
+-        while data.size < chunk_size
+-          tmp = read_data(socket, chunk_size-data.size) # read chunk-data
+-          break unless tmp
+-          data << tmp
+-        end
+-        if data.nil? || data.size != chunk_size
+-          raise BadRequest, "bad chunk data size."
+-        end
++        begin
++          sz = [ chunk_size, BUFSIZE ].min
++          data = read_data(socket, sz) # read chunk-data
++          if data.nil? || data.bytesize != sz
++            raise HTTPStatus::BadRequest, "bad chunk data size."
++          end
++          block.call(data)
++        end while (chunk_size -= sz) > 0
+         read_line(socket)                    # skip CRLF
+-        block.call(data)
+         chunk_size, = read_chunk_size(socket)
+       end
+       read_header(socket)                    # trailer + CRLF
+Index: ruby1.8/lib/webrick/httpservlet/cgihandler.rb
+===================================================================
+--- ruby1.8.orig/lib/webrick/httpservlet/cgihandler.rb
++++ ruby1.8/lib/webrick/httpservlet/cgihandler.rb
+@@ -53,9 +53,7 @@ module WEBrick
+           cgi_in.write("%8d" % dump.size)
+           cgi_in.write(dump)
+ 
+-          if req.body and req.body.size > 0
+-            cgi_in.write(req.body)
+-          end
++          req.body { |chunk| cgi_in.write(chunk) }
+         ensure
+           cgi_in.close
+           status = $?.exitstatus
+Index: ruby1.8/test/webrick/test_httpauth.rb
+===================================================================
+--- ruby1.8.orig/test/webrick/test_httpauth.rb
++++ ruby1.8/test/webrick/test_httpauth.rb
+@@ -3,6 +3,7 @@ require "net/http"
+ require "tempfile"
+ require "webrick"
+ require "webrick/httpauth/basicauth"
++require "stringio"
+ require File.join(File.dirname(__FILE__), "utils.rb")
+ 
+ class TestWEBrickHTTPAuth < Test::Unit::TestCase
+@@ -115,4 +116,98 @@ class TestWEBrickHTTPAuth < Test::Unit::
+       }
+     }
+   end
++
++  def test_digest_auth_int
++    TestWEBrick.start_httpserver{|server, addr, port, log|
++      realm = "wb auth-int realm"
++      path = "/digest_auth_int"
++
++      Tempfile.create("test_webrick_auth_int") {|tmpfile|
++        tmpfile.close
++        tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
++        tmp_pass.set_passwd(realm, "foo", "Hunter2")
++        tmp_pass.flush
++
++        htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
++        users = []
++        htdigest.each{|user, pass| users << user }
++        assert_equal %w(foo), users
++
++        auth = WEBrick::HTTPAuth::DigestAuth.new(
++          :Realm => realm, :UserDB => htdigest,
++          :Algorithm => 'MD5',
++          :Logger => server.logger,
++          :Qop => %w(auth-int),
++        )
++        server.mount_proc(path){|req, res|
++          auth.authenticate(req, res)
++          res.body = "bbb"
++        }
++        Net::HTTP.start(addr, port) do |http|
++          post = Net::HTTP::Post.new(path)
++          params = {}
++          data = 'hello=world'
++          body = StringIO.new(data)
++          post.content_length = data.bytesize
++          post['Content-Type'] = 'application/x-www-form-urlencoded'
++          post.body_stream = body
++
++          http.request(post) do |res|
++            assert_equal('401', res.code, log.call)
++            res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
++              params[key.downcase] = token || quoted.delete('\\')
++            end
++             params['uri'] = "http://#{addr}:#{port}#{path}";
++          end
++
++          body.rewind
++          cred = credentials_for_request('foo', 'Hunter3', params, body)
++          post['Authorization'] = cred
++          post.body_stream = body
++          http.request(post){|res|
++            assert_equal('401', res.code, log.call)
++            assert_not_equal("bbb", res.body, log.call)
++          }
++
++          body.rewind
++          cred = credentials_for_request('foo', 'Hunter2', params, body)
++          post['Authorization'] = cred
++          post.body_stream = body
++          http.request(post){|res| assert_equal("bbb", res.body, log.call)}
++        end
++      }
++    }
++  end
++
++  private
++  def credentials_for_request(user, password, params, body = nil)
++    cnonce = "hoge"
++    nonce_count = 1
++    ha1 = "#{user}:#{params['realm']}:#{password}"
++    if body
++      dig = Digest::MD5.new
++      while buf = body.read(16384)
++        dig.update(buf)
++      end
++      body.rewind
++      ha2 = "POST:#{params['uri']}:#{dig.hexdigest}"
++    else
++      ha2 = "GET:#{params['uri']}"
++    end
++
++    request_digest =
++      "#{Digest::MD5.hexdigest(ha1)}:" \
++      "#{params['nonce']}:#{'%08x' % 
nonce_count}:#{cnonce}:#{params['qop']}:" \
++      "#{Digest::MD5.hexdigest(ha2)}"
++    "Digest username=\"#{user}\"" \
++      ", realm=\"#{params['realm']}\"" \
++      ", nonce=\"#{params['nonce']}\"" \
++      ", uri=\"#{params['uri']}\"" \
++      ", qop=#{params['qop']}" \
++      ", nc=#{'%08x' % nonce_count}" \
++      ", cnonce=\"#{cnonce}\"" \
++      ", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \
++      ", opaque=\"#{params['opaque']}\"" \
++      ", algorithm=#{params['algorithm']}"
++  end
+ end
+Index: ruby1.8/test/webrick/test_httpserver.rb
+===================================================================
+--- ruby1.8.orig/test/webrick/test_httpserver.rb
++++ ruby1.8/test/webrick/test_httpserver.rb
+@@ -257,4 +257,63 @@ class TestWEBrickHTTPServer < Test::Unit
+     assert_equal(started, 1)
+     assert_equal(stopped, 1)
+   end
++
++  def test_gigantic_request_header
++    TestWEBrick.start_httpserver{|server, addr, port, log|
++      server.mount('/', WEBrick::HTTPServlet::FileHandler, __FILE__)
++      TCPSocket.open(addr, port) do |c|
++        c.write("GET / HTTP/1.0\r\n")
++        junk = "X-Junk: #{' ' * 1024}\r\n"
++        assert_raise(Errno::ECONNRESET, Errno::EPIPE) do
++          loop { c.write(junk) }
++        end
++      end
++    }
++  end
++
++  def test_eof_in_chunk
++    TestWEBrick.start_httpserver{|server, addr, port, log|
++      server.mount_proc('/', ->(req, res) { res.body = req.body })
++      TCPSocket.open(addr, port) do |c|
++        c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
++                "Transfer-Encoding: chunked\r\n\r\n5\r\na")
++        c.shutdown(Socket::SHUT_WR) # trigger EOF in server
++        res = c.read
++        assert_match %r{\AHTTP/1\.1 400 }, res
++      end
++    }
++  end
++
++  def test_big_chunks
++    nr_out = 3
++    buf = 'big' # 3 bytes is bigger than 2!
++    config = { :InputBufferSize => 2 }.freeze
++    total = 0
++    all = ''
++    TestWEBrick.start_httpserver(config){|server, addr, port, log|
++      server.mount_proc('/', ->(req, res) {
++        err = []
++        ret = req.body do |chunk|
++          n = chunk.bytesize
++          n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
++          total += n
++          all << chunk
++        end
++        ret.nil? or err << 'req.body should return nil'
++        (buf * nr_out) == all or err << 'input body does not match expected'
++        res.header['connection'] = 'close'
++        res.body = err.join("\n")
++      })
++      TCPSocket.open(addr, port) do |c|
++        c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
++                "Transfer-Encoding: chunked\r\n\r\n")
++        chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
++        nr_out.times { c.write(chunk) }
++        c.write("0\r\n\r\n")
++        head, body = c.read.split("\r\n\r\n")
++        assert_match %r{\AHTTP/1\.1 200 OK}, head
++        assert_nil body
++      end
++    }
++  end
+ end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch
new file mode 100644
index 000000000..f37cf0771
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8778.patch
@@ -0,0 +1,67 @@
+Fix CVE-2018-8778:
+
+https://www.ruby-lang.org/en/news/2018/03/28/buffer-under-read-unpack-cve-2018-8778/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8778
+https://security-tracker.debian.org/tracker/CVE-2018-8778
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From 4cd92d7b13002161a3452a0fe278b877901a8859 Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:38:39 +0000
+Subject: [PATCH 4/4] merge revision(s) 62992:
+
+       pack.c: fix underflow
+
+       * pack.c (pack_unpack_internal): get rid of underflow.
+         https://hackerone.com/reports/298246
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog              | 7 +++++++
+ pack.c                 | 2 +-
+ test/ruby/test_pack.rb | 3 +++
+ version.h              | 2 +-
+ 4 files changed, 12 insertions(+), 2 deletions(-)
+
+Index: ruby1.8/pack.c
+===================================================================
+--- ruby1.8.orig/pack.c
++++ ruby1.8/pack.c
+@@ -13,6 +13,7 @@
+ #include "ruby.h"
+ #include <sys/types.h>
+ #include <ctype.h>
++#include <errno.h>
+ 
+ #define GCC_VERSION_SINCE(major, minor, patchlevel) \
+   (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
+@@ -1385,7 +1386,12 @@ pack_unpack(str, fmt)
+           p++;
+       }
+       else if (ISDIGIT(*p)) {
++          errno = 0;
+           len = strtoul(p, (char**)&p, 10);
++          if (len < 0 || errno) {
++              rb_raise(rb_eRangeError, "pack length too big");
++          }
++
+       }
+       else {
+           len = (type != '@');
+Index: ruby1.8/test/ruby/test_pack.rb
+===================================================================
+--- ruby1.8.orig/test/ruby/test_pack.rb
++++ ruby1.8/test/ruby/test_pack.rb
+@@ -306,4 +306,9 @@ class TestPack < Test::Unit::TestCase
+     assert_equal(["10ef"], "\x10\xef".unpack("H4"))
+     assert_equal(["10ef"], "\x10\xef".unpack("H5"))
+   end
++
++  def test_pack_unpack_atmark
++    pos = (1 << [nil].pack("p").bytesize * 8) - 100 # -100
++    assert_raise(RangeError) {"0123456789".unpack("@#{pos}C10")}
++  end
+ end
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch
new file mode 100644
index 000000000..eb875facb
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8779.patch
@@ -0,0 +1,99 @@
+Fix CVE-2018-8779:
+
+https://www.ruby-lang.org/en/news/2018/03/28/poisoned-nul-byte-unixsocket-cve-2018-8779/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8779
+https://security-tracker.debian.org/tracker/CVE-2018-8779
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Origin: backport, 47165eed264d357e78e27371cfef20d5c2bde5d9
+Reviewed-by: Santiago R.R <address@hidden>
+
+From 47165eed264d357e78e27371cfef20d5c2bde5d9 Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:36:23 +0000
+Subject: [PATCH 3/4] merge revision(s) 62991,63000:
+
+       unixsocket.c: check NUL bytes
+
+       * ext/socket/unixsocket.c (rsock_init_unixsock): check NUL bytes.
+         https://hackerone.com/reports/302997
+
+       unixsocket.c: abstract namespace
+
+       * ext/socket/unixsocket.c (unixsock_path_value): fix r62991 for
+         Linux abstract namespace.
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog                | 12 ++++++++++++
+ ext/socket/unixsocket.c  | 24 +++++++++++++++++++++++-
+ test/socket/test_unix.rb | 10 ++++++++++
+ version.h                |  2 +-
+ 4 files changed, 46 insertions(+), 2 deletions(-)
+
+Index: ruby1.8/test/socket/test_unix.rb
+===================================================================
+--- ruby1.8.orig/test/socket/test_unix.rb
++++ ruby1.8/test/socket/test_unix.rb
+@@ -39,6 +39,16 @@ class TestUNIXSocket < Test::Unit::TestC
+     File.unlink path if path && File.socket?(path)
+   end
+ 
++  def test_open_nul_byte
++    tmpfile = Tempfile.new("s")
++    path = tmpfile.path
++    tmpfile.close(true)
++    assert_raise(ArgumentError) {UNIXServer.open(path+"\0")}
++    assert_raise(ArgumentError) {UNIXSocket.open(path+"\0")}
++  ensure
++    File.unlink path if path && File.socket?(path)
++  end
++
+   def test_addr
+     bound_unix_socket(UNIXServer) {|serv, path|
+       c = UNIXSocket.new(path)
+Index: ruby1.8/ext/socket/socket.c
+===================================================================
+--- ruby1.8.orig/ext/socket/socket.c
++++ ruby1.8/ext/socket/socket.c
+@@ -1623,6 +1623,28 @@ unixsock_connect_internal(arg)
+ }
+ 
+ static VALUE
++unixsock_path_value(VALUE path)
++{
++#ifdef __linux__
++#define TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE 0
++
++    VALUE name = path;
++#if TO_STR_FOR_LINUX_ABSTRACT_NAMESPACE
++    const int isstr = !NIL_P(name = rb_check_string_type(name));
++#else
++    const int isstr = RB_TYPE_P(name, T_STRING);
++#endif
++    if (isstr) {
++        if (RSTRING_LEN(name) == 0 || RSTRING_PTR(name)[0] == '\0') {
++            rb_check_safe_obj(name);
++            return name;             /* ignore encoding */
++        }
++    }
++#endif
++    return rb_get_path(path);
++}
++
++static VALUE
+ init_unixsock(sock, path, server)
+     VALUE sock;
+     VALUE path;
+@@ -1632,7 +1654,7 @@ init_unixsock(sock, path, server)
+     int fd, status;
+     rb_io_t *fptr;
+ 
+-    SafeStringValue(path);
++    path = unixsock_path_value(path);
+     fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
+     if (fd < 0) {
+       rb_sys_fail("socket(2)");
diff --git 
a/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch
new file mode 100644
index 000000000..c7640db14
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch
@@ -0,0 +1,52 @@
+Prepare to fix CVE-2018-{8780,8779}:
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+Index: ruby1.8/file.c
+===================================================================
+--- ruby1.8.orig/file.c
++++ ruby1.8/file.c
+@@ -110,6 +110,41 @@ VALUE rb_cFile;
+ VALUE rb_mFileTest;
+ VALUE rb_cStat;
+ 
++#define insecure_obj_p(obj, level) ((level) >= 4 || ((level) > 0 && 
OBJ_TAINTED(obj)))
++
++static VALUE
++rb_get_path_check(VALUE obj, int level)
++{
++    VALUE tmp;
++    ID to_path;
++    /* skip encoding check - unavailable */
++
++    if (insecure_obj_p(obj, level)) {
++              rb_raise(rb_eSecurityError, "Insecure operation: -r");
++    }
++
++      /* skip check funcall - unvailable */
++      tmp = obj;
++    StringValue(tmp);
++
++    /* skip file_path_convert; useful in WIN32 */
++    if (obj != tmp && insecure_obj_p(tmp, level)) {
++              rb_raise(rb_eSecurityError, "Insecure operation: -r");
++    }
++    /* skip encoding check */
++
++    StringValueCStr(tmp);
++
++    return rb_str_new4(tmp);
++}
++
++VALUE
++rb_get_path(VALUE obj)
++{
++    return rb_get_path_check(obj, rb_safe_level());
++}
++
++
+ static long apply2files _((void (*)(const char *, void *), VALUE, void *));
+ static long
+ apply2files(func, vargs, arg)
diff --git a/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch 
b/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch
new file mode 100644
index 000000000..5bbc8508c
--- /dev/null
+++ b/gnu/packages/patches/ruby-1.8-CVE-2018-8780.patch
@@ -0,0 +1,114 @@
+Fix CVE-2018-8780:
+
+https://www.ruby-lang.org/en/news/2018/03/28/poisoned-nul-byte-dir-cve-2018-8780/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8780
+https://security-tracker.debian.org/tracker/CVE-2018-8780
+
+Patch copied from snapshot.debian.org:
+
+https://snapshot.debian.org/archive/debian-security/20180423T104456Z/pool/updates/main/r/ruby1.8/ruby1.8_1.8.7.358-7.1%2Bdeb7u6.debian.tar.gz
+
+From 143eb22f1877815dd802f7928959c5f93d4c7bb3 Mon Sep 17 00:00:00 2001
+From: usa <address@hidden>
+Date: Wed, 28 Mar 2018 14:27:51 +0000
+Subject: [PATCH 1/4] merge revision(s) 62989:
+
+       dir.c: check NUL bytes
+
+       * dir.c (GlobPathValue): should be used in rb_push_glob only.
+         other methods should use FilePathValue.
+         https://hackerone.com/reports/302338
+
+       * dir.c (rb_push_glob): expand GlobPathValue
+
+git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/address@hidden 
b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+---
+ ChangeLog             | 10 ++++++++++
+ dir.c                 | 22 ++++++++++------------
+ test/ruby/test_dir.rb |  4 ++++
+ version.h             | 10 +++++-----
+ 4 files changed, 29 insertions(+), 17 deletions(-)
+
+Index: ruby1.8/dir.c
+===================================================================
+--- ruby1.8.orig/dir.c
++++ ruby1.8/dir.c
+@@ -392,7 +392,7 @@ dir_initialize(dir, dirname)
+ {
+     struct dir_data *dp;
+ 
+-    SafeStringValue(dirname);
++    FilePathValue(dirname);
+     Data_Get_Struct(dir, struct dir_data, dp);
+     if (dp->dir) closedir(dp->dir);
+     if (dp->path) free(dp->path);
+@@ -1629,8 +1629,15 @@ rb_push_glob(str, flags) /* '\0' is deli
+     long offset = 0;
+     VALUE ary;
+ 
++    /* can contain null bytes as separators */
++    if (!RB_TYPE_P((str), T_STRING)) {
++        FilePathValue(str);
++    }
++    else {
++        rb_check_safe_obj(str);
++        /* unable to check encoding */
++    }
+     ary = rb_ary_new();
+-    SafeStringValue(str);
+ 
+     while (offset < RSTRING_LEN(str)) {
+       int status = push_glob(ary, RSTRING(str)->ptr + offset, flags);
+@@ -1660,7 +1667,7 @@ dir_globs(argc, argv, flags)
+     for (i = 0; i < argc; ++i) {
+       int status;
+       VALUE str = argv[i];
+-      SafeStringValue(str);
++    FilePathValue(str);
+       status = push_glob(ary, RSTRING(str)->ptr, flags);
+       if (status) GLOB_JUMP_TAG(status);
+     }
+Index: ruby1.8/ruby.h
+===================================================================
+--- ruby1.8.orig/ruby.h
++++ ruby1.8/ruby.h
+@@ -257,6 +257,9 @@ void rb_check_safe_str _((VALUE));
+ /* obsolete macro - use SafeStringValue(v) */
+ #define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
+ 
++VALUE rb_get_path(VALUE);
++#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v))
++
+ void rb_secure _((int));
+ RUBY_EXTERN int ruby_safe_level;
+ #define rb_safe_level() (ruby_safe_level)
+@@ -740,6 +743,15 @@ rb_type(obj)
+     return BUILTIN_TYPE(obj);
+ }
+ 
++#define RB_TYPE_P(obj, type) ( \
++      ((type) == T_FIXNUM) ? FIXNUM_P(obj) : \
++      ((type) == T_TRUE) ? ((obj) == Qtrue) : \
++      ((type) == T_FALSE) ? ((obj) == Qfalse) : \
++      ((type) == T_NIL) ? ((obj) == Qnil) : \
++      ((type) == T_UNDEF) ? ((obj) == Qundef) : \
++      ((type) == T_SYMBOL) ? SYMBOL_P(obj) : \
++      (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == (type)))
++
+ static inline int
+ #if defined(HAVE_PROTOTYPES)
+ rb_special_const_p(VALUE obj)
+Index: ruby1.8/test/ruby/test_dir.rb
+===================================================================
+--- ruby1.8.orig/test/ruby/test_dir.rb
++++ ruby1.8/test/ruby/test_dir.rb
+@@ -39,4 +39,9 @@ class TestDir < Test::Unit::TestCase
+       dir.close
+     end
+   end
++
++  def test_foreach
++    assert_equal(Dir.foreach(ROOT).to_a.sort, %w(. ..) + (?a..?z).to_a)
++    assert_raise(ArgumentError) {Dir.foreach(ROOT+"\0").to_a}
++  end
+ end
diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm
index 2fde01685..93f801fa6 100644
--- a/gnu/packages/ruby.scm
+++ b/gnu/packages/ruby.scm
@@ -177,7 +177,25 @@ a focus on simplicity and productivity.")
                            "/ruby-" version ".tar.bz2"))
        (sha256
         (base32
-         "1qq7khilwkayrhwmzlxk83scrmiqfi7lgsn4c63znyvz2c1lgqxl"))))
+         "1qq7khilwkayrhwmzlxk83scrmiqfi7lgsn4c63znyvz2c1lgqxl"))
+       (patches
+        (search-patches "ruby-1.8-CVE-2013-4164.patch"
+                        "ruby-1.8-CVE-2014-8080.patch"
+                        "ruby-1.8-CVE-2014-8090.patch"
+                        "ruby-1.8-CVE-2015-1855.patch"
+                        "ruby-1.8-CVE-2017-10784.patch"
+                        "ruby-1.8-CVE-2017-0898.patch"
+                        "ruby-1.8-CVE-2017-17405.patch"
+                        "ruby-1.8-CVE-2017-17790.patch"
+                        "ruby-1.8-CVE-2018-8780+CVE-2018-8779-pre.patch"
+                        "ruby-1.8-CVE-2018-8780.patch"
+                        "ruby-1.8-CVE-2018-6914.patch"
+                        "ruby-1.8-CVE-2018-8779.patch"
+                        "ruby-1.8-CVE-2018-8778.patch"
+                        "ruby-1.8-CVE-2018-8777+CVE-2017-17742-pre.patch"
+                        "ruby-1.8-CVE-2018-8777.patch"
+                        "ruby-1.8-CVE-2017-17742-pre.patch"
+                        "ruby-1.8-CVE-2017-17742.patch"))))
     (native-search-paths '())
     (arguments
      `(#:test-target "test"
-- 
2.19.2

> Pj.
>
Cheers,
Alex

> On Fri, Nov 23, 2018 at 03:57:29AM +0800, Alex Vong wrote:
>> Hello,
>> 
>> I find out that ruby 1.8, 2.1 and 2.2 are all EOL. Do we still intend to
>> support them (say because they are needed in web development)? If so, I
>> think we should provide security updates.
>> 
>> I have look into Debian LTS support[0]. For 1.8, the LTS support has
>> gone as Debian old old stable[1] is no longer supported since May. For
>> 2.1, it will be supported til 2020 through old stable LTS
>> support[2]. For 2.2, the package was removed when 2.3 was out[3].
>> 
>> What should we do?
>> 
>> [0]: https://wiki.debian.org/LTS
>> [1]: https://tracker.debian.org/pkg/ruby1.8
>> [2]: https://tracker.debian.org/pkg/ruby2.1
>> [3]: https://tracker.debian.org/pkg/ruby2.2
>> 
>> Cheers,
>> Alex

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]