From acb7e81ffb148e1000603862ac9398d53f726b88 Mon Sep 17 00:00:00 2001
From: CentOS Sources
Date: Tue, 9 Nov 2021 04:50:48 -0500
Subject: [PATCH] import zziplib-0.13.68-9.el8
---
.gitignore | 1 +
.zziplib.metadata | 1 +
...ort-documentation-scripts-to-python3.patch | 850 ++++++++++++++++++
SOURCES/CVE-2018-16548.part1.patch | 71 ++
SOURCES/CVE-2018-16548.part2.patch | 50 ++
SOURCES/CVE-2018-16548.part3.patch | 22 +
SOURCES/CVE-2018-17828-singlez.patch | 59 ++
SOURCES/CVE-2018-17828.patch | 341 +++++++
SOURCES/CVE-2018-7725.patch | 48 +
SOURCES/CVE-2018-7726.part1.patch | 31 +
SOURCES/CVE-2018-7726.part2.patch | 40 +
SOURCES/CVE-2018-7726.part3.patch | 22 +
SOURCES/CVE-2018-7727.patch | 138 +++
SOURCES/CVE-2020-18442.patch | 218 +++++
SOURCES/zziplib-0.13.67-multilib-32.patch | 39 +
SOURCES/zziplib-0.13.67-multilib.patch | 42 +
SPECS/zziplib.spec | 299 ++++++
17 files changed, 2272 insertions(+)
create mode 100644 .gitignore
create mode 100644 .zziplib.metadata
create mode 100644 SOURCES/0001-FIX-port-documentation-scripts-to-python3.patch
create mode 100644 SOURCES/CVE-2018-16548.part1.patch
create mode 100644 SOURCES/CVE-2018-16548.part2.patch
create mode 100644 SOURCES/CVE-2018-16548.part3.patch
create mode 100644 SOURCES/CVE-2018-17828-singlez.patch
create mode 100644 SOURCES/CVE-2018-17828.patch
create mode 100644 SOURCES/CVE-2018-7725.patch
create mode 100644 SOURCES/CVE-2018-7726.part1.patch
create mode 100644 SOURCES/CVE-2018-7726.part2.patch
create mode 100644 SOURCES/CVE-2018-7726.part3.patch
create mode 100644 SOURCES/CVE-2018-7727.patch
create mode 100644 SOURCES/CVE-2020-18442.patch
create mode 100644 SOURCES/zziplib-0.13.67-multilib-32.patch
create mode 100644 SOURCES/zziplib-0.13.67-multilib.patch
create mode 100644 SPECS/zziplib.spec
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b1afe1f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/v0.13.68.tar.gz
diff --git a/.zziplib.metadata b/.zziplib.metadata
new file mode 100644
index 0000000..3901f43
--- /dev/null
+++ b/.zziplib.metadata
@@ -0,0 +1 @@
+bf62bf6138a7a5bddbad41d6c5dbb169e1528110 SOURCES/v0.13.68.tar.gz
diff --git a/SOURCES/0001-FIX-port-documentation-scripts-to-python3.patch b/SOURCES/0001-FIX-port-documentation-scripts-to-python3.patch
new file mode 100644
index 0000000..ba0cba3
--- /dev/null
+++ b/SOURCES/0001-FIX-port-documentation-scripts-to-python3.patch
@@ -0,0 +1,850 @@
+From f04dd2918b15853e866d3941b72005696c8c3b8f Mon Sep 17 00:00:00 2001
+From: Jakub Martisko
+Date: Tue, 3 Jul 2018 09:33:07 +0200
+Subject: [PATCH] FIX: port documentation scripts to python3
+
+---
+ configure | 2 +-
+ configure.ac | 2 +-
+ docs/cpp2markdown-1.py | 9 ++++--
+ docs/cpp2markdown.py | 6 ++--
+ docs/make-doc.py | 56 ++++++++++++++++++-----------------
+ docs/makedocs.py | 26 ++++++++--------
+ docs/zzipdoc/commentmarkup.py | 5 ++--
+ docs/zzipdoc/dbk2htm.py | 5 ++--
+ docs/zzipdoc/docbookdocument.py | 34 +++++++++++----------
+ docs/zzipdoc/functionheader.py | 3 +-
+ docs/zzipdoc/functionlisthtmlpage.py | 14 +++++----
+ docs/zzipdoc/functionlistreference.py | 8 +++--
+ docs/zzipdoc/functionprototype.py | 3 +-
+ docs/zzipdoc/htm2dbk.py | 10 ++++---
+ docs/zzipdoc/htmldocument.py | 34 +++++++++++----------
+ docs/zzipdoc/match.py | 17 ++++++-----
+ docs/zzipdoc/options.py | 5 ++--
+ docs/zzipdoc/textfile.py | 6 ++--
+ docs/zzipdoc/textfileheader.py | 6 ++--
+ 18 files changed, 140 insertions(+), 109 deletions(-)
+
+diff --git a/configure b/configure
+index 72a5b6c..6ff3ee4 100755
+--- a/configure
++++ b/configure
+@@ -12270,7 +12270,7 @@ fi
+ done
+ test -n "$PERL" || PERL="echo no perl found for"
+
+-for ac_prog in python
++for ac_prog in python3
+ do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+diff --git a/configure.ac b/configure.ac
+index 4708f8d..68aeb73 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -87,7 +87,7 @@ AX_CREATE_PKGCONFIG_INFO(dnl
+ AX_PAX_TAR_CREATE
+ AX_PAX_TAR_EXTRACT
+ AC_PATH_PROGS(PERL, perl5 perl, echo no perl found for)
+-AC_PATH_PROGS(PYTHON, python, echo no python found for)
++AC_PATH_PROGS(PYTHON, python3, echo no python found for)
+ AC_PATH_PROGS(MKZIP, zip pkzip, :)
+ AC_PATH_PROGS(XMLTO, xmlto, :)
+
+diff --git a/docs/cpp2markdown-1.py b/docs/cpp2markdown-1.py
+index 60d28c4..1deaed9 100755
+--- a/docs/cpp2markdown-1.py
++++ b/docs/cpp2markdown-1.py
+@@ -1,9 +1,12 @@
+ #! /usr/bin/env python
++from __future__ import absolute_import
++from __future__ import print_function
+ import pygments.lexers.compiled as lexer
+ import optparse
+ import re
+ from pygments.token import Token
+ import logging
++from six.moves import range
+
+ logg = logging.getLogger(__name__)
+
+@@ -39,7 +42,7 @@ class CppToMarkdown:
+ check2 = re.compile(r"^\s[*]\s+\b[Cc]opyright\b")
+ empty1 = re.compile(r"^\s[*]\s*$")
+ state = "intro"
+- for i in xrange(1,len(lines)-1):
++ for i in range(1,len(lines)-1):
+ line = lines[i]
+ if state == "intro":
+ if empty1.match(line):
+@@ -108,7 +111,7 @@ class CppToMarkdown:
+ def run(self, filename):
+ filetext = open(filename).read()
+ for line in self.process(filetext, filename):
+- print line
++ print(line)
+ def process(self, filetext, filename=""):
+ section_ruler = "-----------------------------------------"
+ copyright = ""
+@@ -136,7 +139,7 @@ class CppToMarkdown:
+ else:
+ if text:
+ yield "#### NOTES"
+- print token, text.replace("\n", "\n ")
++ print(token, text.replace("\n", "\n "))
+ if copyright:
+ yield section_ruler
+ yield "### COPYRIGHT"
+diff --git a/docs/cpp2markdown.py b/docs/cpp2markdown.py
+index 710bbdc..b8fe11d 100644
+--- a/docs/cpp2markdown.py
++++ b/docs/cpp2markdown.py
+@@ -1,3 +1,5 @@
++from __future__ import absolute_import
++from __future__ import print_function
+ import pygments.lexers.compiled as lexer
+ import optparse
+ import re
+@@ -62,7 +64,7 @@ class CppToMarkdown:
+ def run(self, filename):
+ filetext = open(filename).read()
+ for line in self.process(filetext, filename):
+- print line
++ print(line)
+ def process(self, filetext, filename=""):
+ for token, text in self.parse(filetext):
+ if token == FileInclude:
+@@ -86,7 +88,7 @@ class CppToMarkdown:
+ else:
+ if text:
+ yield "#### NOTES"
+- print token, text.replace("\n", "\n ")
++ print(token, text.replace("\n", "\n "))
+ def isexported_function(self):
+ function = self.function_text.strip().replace("\n"," ")
+ logg.debug("@ --------------------------------------")
+diff --git a/docs/make-doc.py b/docs/make-doc.py
+index f12553f..22775ef 100644
+--- a/docs/make-doc.py
++++ b/docs/make-doc.py
+@@ -1,5 +1,7 @@
+ #! /usr/bin/python
+ # -*- coding: UTF-8 -*-
++from __future__ import absolute_import
++from __future__ import print_function
+ import sys
+ import re
+ import string
+@@ -23,7 +25,7 @@ def s(string, pattern, repl, count=0):
+ def m(string, pattern):
+ return re.match(pattern, string)
+ def sorted_keys(dict):
+- keys = dict.keys()
++ keys = list(dict.keys())
+ keys.sort()
+ return keys
+
+@@ -59,18 +61,18 @@ def section2html(text):
+ "" : "", "
" : "
" ,
+ "" : "", "" : "" }
+ for str in mapping:
+- text = string.replace(text, str, mapping[str])
++ text = text.replace(str, mapping[str])
+ return text
+ def html(text):
+ return section2html(paramdef2html(text))
+ def cdata1(text):
+- return string.replace(text, "&", "&")
++ return text.replace("&", "&")
+ def cdata31(text):
+- return string.replace(string.replace(text, "<","<"), ">",">")
++ return text.replace(text, "<","<").replace( ">",">")
+ def cdata3(text):
+ return cdata31(cdata1(text))
+ def cdata43(text):
+- return string.replace(text,"\"", """)
++ return text.replace("\"", """)
+ def cdata41(text):
+ return cdata43(cdata31(text))
+ def cdata4(text):
+@@ -126,7 +128,7 @@ def this_function_link(text, name):
+ class Options:
+ var = {}
+ def __getattr__(self, name):
+- if not self.var.has_key(name): return None
++ if name not in self.var: return None
+ return self.var[name]
+ def __setattr__(self, name, value):
+ self.var[name] = value
+@@ -158,7 +160,7 @@ class File:
+ self.copyright = ""
+ def __getattr__(self, name):
+ """ defend against program to break on uninited members """
+- if self.__dict__.has_key(name): return self.__dict__[name]
++ if name in self.__dict__: return self.__dict__[name]
+ warn("no such member: "+name); return None
+ def set_author(self, text):
+ if self.authors:
+@@ -215,7 +217,7 @@ def scan_options (options, list):
+ #else
+ try:
+ input = open(name, "r")
+- except IOError, error:
++ except IOError as error:
+ warn(#...... (scan_options) ...............
+ "can not open input file: "+name, error)
+ continue
+@@ -294,12 +296,12 @@ class Function:
+ # return ""
+ def __getattr__(self, name):
+ """ defend against program exit on members being not inited """
+- if self.__dict__.has_key(name): return self.__dict__[name]
++ if name in self.__dict__: return self.__dict__[name]
+ warn("no such member: "+name); return None
+ def dict(self):
+ return self.__dict__
+ def dict_sorted_keys(self):
+- keys = self.__dict__.keys()
++ keys = list(self.__dict__.keys())
+ keys.sort()
+ return keys
+ def parse(self, prototype):
+@@ -376,7 +378,7 @@ def examine_head_anchors(func_list):
+ function.head = s(function.head, r"(.*)also:(.*)", lambda x
+ : set_seealso(function, x.group(2)) and x.group(1))
+ if function.seealso and None:
+- print "function[",function.name,"].seealso=",function.seealso
++ print("function[",function.name,"].seealso=",function.seealso)
+ examine_head_anchors(function_list)
+
+ # =============================================================== HTML =====
+@@ -455,7 +457,7 @@ def combined_html_pages(func_list):
+ s(ensure_name(this_function_link(section2html( func.body ),
+ func.name), func.name),
+ r"(?sx) (?para>\s*)
", r"\1"))
+- return combined.values()
++ return list(combined.values())
+ html_pages = combined_html_pages(function_list)
+
+ def html_resolve_links_on_page(text, list):
+@@ -495,7 +497,7 @@ class HtmlPage:
+ return T
+ def add_page_map(self, list):
+ """ generate the index-block at the start of the onepage-html file """
+- keys = list.keys()
++ keys = list(list.keys())
+ keys.sort()
+ for name in keys:
+ self.toc += "\n"+ \
+@@ -524,11 +526,11 @@ html.add_page_list(html_pages)
+ # and finally print the html-formatted output
+ try:
+ F = open(o.libhtmlfile, "w")
+-except IOError, error:
++except IOError as error:
+ warn(# ............. open(o.libhtmlfile, "w") ..............
+ "can not open html output file: "+o.libhtmlfile, error)
+ else:
+- print >> F, html.page_text()
++ print(html.page_text(), file=F)
+ F.close()
+ #fi
+
+@@ -987,40 +989,40 @@ doctype += '"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">'+"\n"
+
+ try:
+ F = open(o.docbookfile,"w")
+-except IOError, error:
++except IOError as error:
+ warn("can not open docbook output file: "+o.docbookfile, error)
+ else:
+- print >> F, doctype, 'Manual Pages'
++ print(doctype, 'Manual Pages', file=F)
+
+ for page in combined_pages:
+- print >> F, page.refentry_text()
++ print(page.refentry_text(), file=F)
+ #od
+
+ for page in header_refpages.values():
+ if not page.refentry: continue
+- print >> F, "\n",
+- print >> F, page.refentry_text()
++ print("\n", end=' ', file=F)
++ print(page.refentry_text(), file=F)
+ #od
+
+- print >> F, "\n",'',"\n"
++ print("\n",'',"\n", file=F)
+ F.close()
+ #fi
+
+ # _____________________________________________________________________
+ try:
+ F = open( o.dumpdocfile, "w")
+-except IOError, error:
++except IOError as error:
+ warn ("can not open"+o.dumpdocfile,error)
+ else:
+ for func in function_list:
+ name = func.name
+- print >> F, ""+"\n"
++ print(""+"\n", file=F)
+ for H in sorted_keys(func.dict()):
+- print >> F, "<"+H+" name=\""+name+"\">",
+- print >> F, str(func.dict()[H]),
+- print >> F, ""+H+">"
++ print("<"+H+" name=\""+name+"\">", end=' ', file=F)
++ print(str(func.dict()[H]), end=' ', file=F)
++ print(""+H+">", file=F)
+ #od
+- print >> F, "\n\n";
++ print("\n\n", file=F);
+ #od
+ F.close();
+ #fi
+diff --git a/docs/makedocs.py b/docs/makedocs.py
+index 1bc8f88..d987292 100644
+--- a/docs/makedocs.py
++++ b/docs/makedocs.py
+@@ -1,3 +1,5 @@
++from __future__ import absolute_import
++from __future__ import print_function
+ import sys
+ from zzipdoc.match import *
+ from zzipdoc.options import *
+@@ -37,7 +39,7 @@ class PerFile:
+ return None
+ def print_list_mainheader(self):
+ for t_fileheader in self.headers:
+- print t_fileheader.get_filename(), t_fileheader.src_mainheader()
++ print(t_fileheader.get_filename(), t_fileheader.src_mainheader())
+
+ class PerFunctionEntry:
+ def __init__(self, header, comment, prototype):
+@@ -66,10 +68,10 @@ class PerFunction:
+ functionprototype) ]
+ def print_list_titleline(self):
+ for funcheader in self.headers:
+- print funcheader.get_filename(), "[=>]", funcheader.get_titleline()
++ print(funcheader.get_filename(), "[=>]", funcheader.get_titleline())
+ def print_list_name(self):
+ for funcheader in self.prototypes:
+- print funcheader.get_filename(), "[>>]", funcheader.get_name()
++ print(funcheader.get_filename(), "[>>]", funcheader.get_name())
+
+ class PerFunctionFamilyEntry:
+ def __init__(self, leader):
+@@ -122,12 +124,12 @@ class PerFunctionFamily:
+ for name in self.retarget:
+ into = self.retarget[name]
+ if into not in name_list:
+- print ("function '"+name+"' retarget into '"+into+
+- "' does not exist - keep alone")
++ print(("function '"+name+"' retarget into '"+into+
++ "' does not exist - keep alone"))
+ if into in self.retarget:
+ other = self.retarget[into]
+- print ("function '"+name+"' retarget into '"+into+
+- "' which is itself a retarget into '"+other+"'")
++ print(("function '"+name+"' retarget into '"+into+
++ "' which is itself a retarget into '"+other+"'"))
+ if into not in lead_list:
+ lead_list += [ into ]
+ for func in self.functions:
+@@ -141,7 +143,7 @@ class PerFunctionFamily:
+ entry.add(func) # the first
+ self.entries += [ entry ]
+ else:
+- print "head function '"+name+" has no entry"
++ print("head function '"+name+" has no entry")
+ for func in self.functions:
+ name = func.get_name()
+ if name in self.retarget:
+@@ -150,14 +152,14 @@ class PerFunctionFamily:
+ if entry is not None:
+ entry.add(func) # will not add duplicates
+ else:
+- print "into function '"+name+" has no entry"
++ print("into function '"+name+" has no entry")
+ def print_list_name(self):
+ for family in self.entries:
+ name = family.get_name()
+- print name, ":",
++ print(name, ":", end=' ')
+ for item in family.functions:
+- print item.get_name(), ",",
+- print ""
++ print(item.get_name(), ",", end=' ')
++ print("")
+ class HtmlManualPageAdapter:
+ def __init__(self, entry):
+ """ usually takes a PerFunctionEntry """
+diff --git a/docs/zzipdoc/commentmarkup.py b/docs/zzipdoc/commentmarkup.py
+index 3f605a7..31727a3 100644
+--- a/docs/zzipdoc/commentmarkup.py
++++ b/docs/zzipdoc/commentmarkup.py
+@@ -1,4 +1,5 @@
+-from match import Match
++from __future__ import absolute_import
++from .match import Match
+
+ def markup_link_syntax(text):
+ """ markup the link-syntax ` => somewhere ` in the text block """
+@@ -31,7 +32,7 @@ class CommentMarkup:
+ comment = self.header.comment
+ try:
+ comment = self.header.get_otherlines()
+- except Exception, e:
++ except Exception as e:
+ pass
+ mode = ""
+ text = ""
+diff --git a/docs/zzipdoc/dbk2htm.py b/docs/zzipdoc/dbk2htm.py
+index f8593e6..2b68e95 100644
+--- a/docs/zzipdoc/dbk2htm.py
++++ b/docs/zzipdoc/dbk2htm.py
+@@ -1,4 +1,5 @@
+-from match import Match
++from __future__ import absolute_import
++from .match import Match
+ import string
+
+ class dbk2htm_conversion:
+@@ -9,7 +10,7 @@ class dbk2htm_conversion:
+ pass
+ def section2html(self, text):
+ for str in self.mapping:
+- text = string.replace(text, str, self.mapping[str])
++ text = text.replace(str, self.mapping[str])
+ return text
+ def paramdef2html(self, text):
+ s = Match()
+diff --git a/docs/zzipdoc/docbookdocument.py b/docs/zzipdoc/docbookdocument.py
+index c4602ad..44a0b23 100644
+--- a/docs/zzipdoc/docbookdocument.py
++++ b/docs/zzipdoc/docbookdocument.py
+@@ -1,6 +1,8 @@
+ #! /usr/bin/env python
+ # -*- coding: UTF-8 -*-
+-from match import Match
++from __future__ import absolute_import
++from __future__ import print_function
++from .match import Match
+
+ class DocbookDocument:
+ """ binds some xml content page with additional markup - in this
+@@ -23,14 +25,14 @@ class DocbookDocument:
+ def get_title(self):
+ if self.title: return title
+ try: return self.text[0].get_title()
+- except Exception, e: pass
++ except Exception as e: pass
+ return self.title
+ def _xml_doctype(self, rootnode):
+ return ""
+ def _xml_text(self, xml):
+ """ accepts adapter objects with .xml_text() """
+ try: return xml.xml_text()
+- except Exception, e: print "DocbookDocument/text", e; pass
++ except Exception as e: print("DocbookDocument/text", e); pass
+ return str(xml)
+ def _fetch_rootnode(self, text):
+ fetch = Match(r"^[^<>]*<(\w+)\b")
+@@ -47,7 +49,7 @@ class DocbookDocument:
+ return filename
+ def save(self, filename = None):
+ filename = self._filename(filename)
+- print "writing '"+filename+"'"
++ print("writing '"+filename+"'")
+ if len(self.text) > 1:
+ self.save_all(filename)
+ else:
+@@ -58,12 +60,12 @@ class DocbookDocument:
+ xml_text = self._xml_text(text)
+ rootnode = self._fetch_rootnode(xml_text)
+ doctype = self._xml_doctype(rootnode)
+- print >>fd, doctype
+- print >>fd, xml_text
++ print(doctype, file=fd)
++ print(xml_text, file=fd)
+ fd.close()
+ return True
+- except IOError, e:
+- print "could not open '"+filename+"'file", e
++ except IOError as e:
++ print("could not open '"+filename+"'file", e)
+ return False
+ def save_all(self, filename):
+ assert len(self.text) > 1
+@@ -76,20 +78,20 @@ class DocbookDocument:
+ else:
+ rootnode = self.rootnode
+ doctype = self._xml_doctype(rootnode)
+- print >>fd, doctype
++ print(doctype, file=fd)
+ title = self.get_title()
+ if title and self.rootnode in self.has_title_child:
+- print >>fd, "<"+self.rootnode+'>'+title+''
++ print("<"+self.rootnode+'>'+title+'', file=fd)
+ elif title:
+- print >>fd, "<"+self.rootnode+' id="'+title+'">'
++ print("<"+self.rootnode+' id="'+title+'">', file=fd)
+ else:
+- print >>fd, "<"+self.rootnode+'>'
++ print("<"+self.rootnode+'>', file=fd)
+ for text in self.text:
+ text = self._xml_text(text)
+- print >>fd, text
+- print >>fd, ""+self.rootnode+">"
++ print(text, file=fd)
++ print(""+self.rootnode+">", file=fd)
+ fd.close()
+ return True
+- except IOError, e:
+- print "could not open '"+filename+"'file", e
++ except IOError as e:
++ print("could not open '"+filename+"'file", e)
+ return False
+diff --git a/docs/zzipdoc/functionheader.py b/docs/zzipdoc/functionheader.py
+index 81bb385..a424a6d 100644
+--- a/docs/zzipdoc/functionheader.py
++++ b/docs/zzipdoc/functionheader.py
+@@ -1,4 +1,5 @@
+-from match import Match
++from __future__ import absolute_import
++from .match import Match
+
+ class FunctionHeader:
+ """ parsing the comment block that is usually presented before
+diff --git a/docs/zzipdoc/functionlisthtmlpage.py b/docs/zzipdoc/functionlisthtmlpage.py
+index 4ec9178..8009194 100644
+--- a/docs/zzipdoc/functionlisthtmlpage.py
++++ b/docs/zzipdoc/functionlisthtmlpage.py
+@@ -1,5 +1,7 @@
+-from options import *
+-from match import Match
++from __future__ import absolute_import
++from __future__ import print_function
++from .options import *
++from .match import Match
+
+ class FunctionListHtmlPage:
+ """ The main part here is to create a TOC (table of contents) at the
+@@ -35,7 +37,7 @@ class FunctionListHtmlPage:
+ head_text = entry.head_xml_text()
+ body_text = entry.body_xml_text(name)
+ if not head_text:
+- print "no head_text for", name
++ print("no head_text for", name)
+ return
+ try:
+ prespec = entry.head_get_prespec()
+@@ -43,7 +45,7 @@ class FunctionListHtmlPage:
+ callspec = entry.head_get_callspec()
+ head_text = (""+namespec+""
+ +callspec+" : "+prespec+"
")
+- except Exception, e:
++ except Exception as e:
+ pass
+ try:
+ extraline = ""
+@@ -56,7 +58,7 @@ class FunctionListHtmlPage:
+ ''+filename+''+
+ '')
+ body_text = extraline + body_text
+- except Exception, e:
++ except Exception as e:
+ pass
+ def link(text):
+ return (text & Match("(\w*)")
+@@ -102,7 +104,7 @@ class FunctionListHtmlPage:
+ text &= (Match("(?s)(\w+)")
+ >> (lambda x: self.resolve_internal(x.group(1))))
+ if len(self.not_found_in_anchors):
+- print "not found in anchors: ", self.not_found_in_anchors
++ print("not found in anchors: ", self.not_found_in_anchors)
+ return (text & Match("(?s)([^<>]*)")
+ >> "\\1
")
+ def resolve_external(self, func, sect):
+diff --git a/docs/zzipdoc/functionlistreference.py b/docs/zzipdoc/functionlistreference.py
+index c38ff0a..5993d45 100644
+--- a/docs/zzipdoc/functionlistreference.py
++++ b/docs/zzipdoc/functionlistreference.py
+@@ -1,7 +1,9 @@
+ #! /usr/bin/env python
+ # -*- coding: UTF-8 -*-
+-from match import Match
+-from htm2dbk import *
++from __future__ import absolute_import
++from __future__ import print_function
++from .match import Match
++from .htm2dbk import *
+
+ class FunctionListReference:
+ """ Creating a docbook-style list of parts
+@@ -19,7 +21,7 @@ class FunctionListReference:
+ description = entry.body_xml_text(name)
+ funcsynopsis = entry.head_xml_text()
+ if not funcsynopsis:
+- print "no funcsynopsis for", name
++ print("no funcsynopsis for", name)
+ return
+ if self.entry is None:
+ self.entry = FunctionListRefEntry(entry, self.o)
+diff --git a/docs/zzipdoc/functionprototype.py b/docs/zzipdoc/functionprototype.py
+index fda85bb..1247f6c 100644
+--- a/docs/zzipdoc/functionprototype.py
++++ b/docs/zzipdoc/functionprototype.py
+@@ -1,4 +1,5 @@
+-from match import Match
++from __future__ import absolute_import
++from .match import Match
+
+ class FunctionPrototype:
+ """ takes a single function prototype line (cut from some source file)
+diff --git a/docs/zzipdoc/htm2dbk.py b/docs/zzipdoc/htm2dbk.py
+index ec9685b..12b70dd 100644
+--- a/docs/zzipdoc/htm2dbk.py
++++ b/docs/zzipdoc/htm2dbk.py
+@@ -6,8 +6,10 @@ The mapping of markups and links is far from perfect. But all we
+ want is the docbook-to-pdf converter and similar technology being
+ present in the world of docbook-to-anything converters. """
+
++from __future__ import absolute_import
++from __future__ import print_function
+ from datetime import date
+-import match
++from . import match
+ import sys
+
+ m = match.Match
+@@ -146,8 +148,8 @@ def htm2dbk_files(args):
+ doc.filename = filename
+ doc.add(f.read())
+ f.close()
+- except IOError, e:
+- print >> sys.stderr, "can not open "+filename
++ except IOError as e:
++ print("can not open "+filename, file=sys.stderr)
+ return doc.value()
+
+ def html2docbook(text):
+@@ -155,4 +157,4 @@ def html2docbook(text):
+ return htm2dbk_conversion().convert2(text)
+
+ if __name__ == "__main__":
+- print htm2dbk_files(sys.argv[1:])
++ print(htm2dbk_files(sys.argv[1:]))
+diff --git a/docs/zzipdoc/htmldocument.py b/docs/zzipdoc/htmldocument.py
+index 47d58dc..5e4445a 100644
+--- a/docs/zzipdoc/htmldocument.py
++++ b/docs/zzipdoc/htmldocument.py
+@@ -1,6 +1,8 @@
+ #! /usr/bin/env python
+ # -*- coding: UTF-8 -*-
+-from match import Match
++from __future__ import absolute_import
++from __future__ import print_function
++from .match import Match
+
+ class HtmlDocument:
+ """ binds some html content page with additional markup - in this
+@@ -29,31 +31,31 @@ class HtmlDocument:
+ def get_title(self):
+ if self.title: return self.title
+ try: return self.text[0].get_title()
+- except Exception, e: pass
++ except Exception as e: pass
+ return self.title
+ def _html_meta(self, meta):
+ """ accepts adapter objects with .html_meta() """
+ try: return meta.html_meta()
+- except Exception, e: pass
++ except Exception as e: pass
+ return str(meta)
+ def _html_style(self, style):
+ """ accepts adapter objects with .html_style() and .xml_style() """
+ ee = None
+ try: return style.html_style()
+- except Exception, e: ee = e; pass
++ except Exception as e: ee = e; pass
+ try: return style.xml_style()
+- except Exception, e: print "HtmlDocument/style", ee, e; pass
++ except Exception as e: print("HtmlDocument/style", ee, e); pass
+ try: return str(style)
+- except Exception, e: print "HtmlDocument/style", e; return ""
++ except Exception as e: print("HtmlDocument/style", e); return ""
+ def _html_text(self, html):
+ """ accepts adapter objects with .html_text() and .xml_text() """
+ ee = None
+ try: return html.html_text()
+- except Exception, e: ee = e; pass
++ except Exception as e: ee = e; pass
+ try: return html.xml_text()
+- except Exception, e: print "HtmlDocument/text", ee, e; pass
++ except Exception as e: print("HtmlDocument/text", ee, e); pass
+ try: return str(html)
+- except Exception, e: print "HtmlDocument/text", e; return " "
++ except Exception as e: print("HtmlDocument/text", e); return " "
+ def navigation(self):
+ if self.navi:
+ return self.navi
+@@ -63,7 +65,7 @@ class HtmlDocument:
+ self.navi = fd.read()
+ fd.close()
+ return self.navi
+- except Exception, e:
++ except Exception as e:
+ pass
+ return None
+ def html_header(self):
+@@ -103,15 +105,15 @@ class HtmlDocument:
+ return filename
+ def save(self, filename = None):
+ filename = self._filename(filename)
+- print "writing '"+filename+"'"
++ print("writing '"+filename+"'")
+ try:
+ fd = open(filename, "w")
+- print >>fd, self.html_header()
++ print(self.html_header(), file=fd)
+ for text in self.text:
+- print >>fd, self._html_text(text)
+- print >>fd, self.html_footer()
++ print(self._html_text(text), file=fd)
++ print(self.html_footer(), file=fd)
+ fd.close()
+ return True
+- except IOError, e:
+- print "could not open '"+filename+"'file", e
++ except IOError as e:
++ print("could not open '"+filename+"'file", e)
+ return False
+diff --git a/docs/zzipdoc/match.py b/docs/zzipdoc/match.py
+index a089ec3..5f12478 100644
+--- a/docs/zzipdoc/match.py
++++ b/docs/zzipdoc/match.py
+@@ -3,7 +3,10 @@
+ # @creator (C) 2003 Guido U. Draheim
+ # @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
+
++from __future__ import absolute_import
++from __future__ import print_function
+ import re
++import six
+
+ # ---------------------------------------------------------- Regex Match()
+ # beware, stupid python interprets backslashes in replace-parts only partially!
+@@ -18,7 +21,7 @@ class MatchReplace:
+ MatchReplace.__call__(self, matching, template, count, flags)
+ def __call__(self, matching, template = None, count = 0, flags = None):
+ """ other than __init__ the template may be left off to be unchanged"""
+- if isinstance(count, basestring): # count/flags swapped over?
++ if isinstance(count, six.string_types): # count/flags swapped over?
+ flags = count; count = 0
+ if isinstance(matching, Match):
+ self.matching = matching
+@@ -57,7 +60,7 @@ class Match(str):
+ def __call__(self, pattern, flags = None):
+ assert isinstance(pattern, str) or pattern is None
+ assert isinstance(flags, str) or flags is None
+- str.__init__(self, pattern)
++ super(Match,self).__init__()
+ self.replaced = 0 # set by subn() inside MatchReplace
+ self.found = None # set by search() to a MatchObject
+ self.pattern = pattern
+@@ -90,14 +93,14 @@ class Match(str):
+ if __name__ == "__main__":
+ # matching:
+ if "foo" & Match("oo"):
+- print "oo"
++ print("oo")
+ x = Match()
+ if "foo" & x("(o+)"):
+- print x[1]
++ print(x[1])
+ # replacing:
+ y = "fooboo" & Match("oo") >> "ee"
+- print y
++ print(y)
+ r = Match("oo") >> "ee"
+- print "fooboo" & r
++ print("fooboo" & r)
+ s = MatchReplace("oo", "ee")
+- print "fooboo" & s
++ print("fooboo" & s)
+diff --git a/docs/zzipdoc/options.py b/docs/zzipdoc/options.py
+index c6758d5..4a93bb7 100644
+--- a/docs/zzipdoc/options.py
++++ b/docs/zzipdoc/options.py
+@@ -3,13 +3,14 @@
+ # @creator (C) 2003 Guido U. Draheim
+ # @license http://creativecommons.org/licenses/by-nc-sa/2.0/de/
+
+-from match import Match
++from __future__ import absolute_import
++from .match import Match
+
+ # use as o.optionname to check for commandline options.
+ class Options:
+ var = {}
+ def __getattr__(self, name):
+- if not self.var.has_key(name): return None
++ if name not in self.var: return None
+ return self.var[name]
+ def __setattr__(self, name, value):
+ self.var[name] = value
+diff --git a/docs/zzipdoc/textfile.py b/docs/zzipdoc/textfile.py
+index bfaff8d..9fabeac 100644
+--- a/docs/zzipdoc/textfile.py
++++ b/docs/zzipdoc/textfile.py
+@@ -1,4 +1,6 @@
+
++from __future__ import absolute_import
++from six.moves import range
+ def _src_to_xml(text):
+ return text.replace("&", "&").replace("<", "<").replace(">", ">")
+
+@@ -17,7 +19,7 @@ class TextFile:
+ self.src_text = fd.read()
+ fd.close()
+ return True
+- except IOError, e:
++ except IOError as e:
+ pass
+ return False
+ def assert_src_text(self):
+@@ -41,7 +43,7 @@ class TextFile:
+ self._line(self.src_text, offset)
+ def _line(self, text, offset):
+ line = 1
+- for x in xrange(0,offset):
++ for x in range(0,offset):
+ if x == "\n":
+ line += 1
+ return line
+diff --git a/docs/zzipdoc/textfileheader.py b/docs/zzipdoc/textfileheader.py
+index ceaa28e..63be1e1 100644
+--- a/docs/zzipdoc/textfileheader.py
++++ b/docs/zzipdoc/textfileheader.py
+@@ -1,4 +1,6 @@
+-from match import Match
++from __future__ import absolute_import
++from __future__ import print_function
++from .match import Match
+
+ class TextFileHeader:
+ """ scan for a comment block at the source file start and fill the
+@@ -17,7 +19,7 @@ class TextFileHeader:
+ x = Match()
+ text = self.textfile.get_src_text()
+ if not text:
+- print "nonexistent file:", self.textfile.get_filename()
++ print("nonexistent file:", self.textfile.get_filename())
+ return False
+ if text & x(r"(?s)[/][*]+(\s(?:.(?!\*\/))*.)\*\/"
+ r"(?:\s*\#(?:define|ifdef|endif)[ ]*\S*[ ]*\S*)*"
+--
+2.14.4
+
diff --git a/SOURCES/CVE-2018-16548.part1.patch b/SOURCES/CVE-2018-16548.part1.patch
new file mode 100644
index 0000000..25c2b74
--- /dev/null
+++ b/SOURCES/CVE-2018-16548.part1.patch
@@ -0,0 +1,71 @@
+From 9411bde3e4a70a81ff3ffd256b71927b2d90dcbb Mon Sep 17 00:00:00 2001
+From: jmoellers
+Date: Fri, 7 Sep 2018 11:32:04 +0200
+Subject: [PATCH] Avoid memory leak from __zzip_parse_root_directory().
+
+---
+ test/test.zip | Bin 1361 -> 1361 bytes
+ zzip/zip.c | 36 ++++++++++++++++++++++++++++++++++--
+ 2 files changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index 88b833b..a685280 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -475,9 +475,15 @@ __zzip_parse_root_directory(int fd,
+ } else
+ {
+ if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0)
++ {
++ free(hdr0);
+ return ZZIP_DIR_SEEK;
++ }
+ if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent))
++ {
++ free(hdr0);
+ return ZZIP_DIR_READ;
++ }
+ d = &dirent;
+ }
+
+@@ -577,12 +583,38 @@ __zzip_parse_root_directory(int fd,
+
+ if (hdr_return)
+ *hdr_return = hdr0;
++ else
++ {
++ /* If it is not assigned to *hdr_return, it will never be free()'d */
++ free(hdr0);
++ /* Make sure we don't free it again in case of error */
++ hdr0 = NULL;
++ }
+ } /* else zero (sane) entries */
+ # ifndef ZZIP_ALLOW_MODULO_ENTRIES
+- return (entries != zz_entries ? ZZIP_CORRUPTED : 0);
++ if (entries != zz_entries)
++ {
++ /* If it was assigned to *hdr_return, undo assignment */
++ if (p_reclen && hdr_return)
++ *hdr_return = NULL;
++ /* Free it, if it was not already free()'d */
++ if (hdr0 != NULL)
++ free(hdr0);
++ return ZZIP_CORRUPTED;
++ }
+ # else
+- return ((entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0);
++ if (((entries & (unsigned)0xFFFF) != zz_entries)
++ {
++ /* If it was assigned to *hdr_return, undo assignment */
++ if (p_reclen && hdr_return)
++ *hdr_return = NULL;
++ /* Free it, if it was not already free()'d */
++ if (hdr0 != NULL)
++ free(hdr0);
++ return ZZIP_CORRUPTED;
++ }
+ # endif
++ return 0;
+ }
+
+ /* ------------------------- high-level interface ------------------------- */
diff --git a/SOURCES/CVE-2018-16548.part2.patch b/SOURCES/CVE-2018-16548.part2.patch
new file mode 100644
index 0000000..b9bea26
--- /dev/null
+++ b/SOURCES/CVE-2018-16548.part2.patch
@@ -0,0 +1,50 @@
+From d2e5d5c53212e54a97ad64b793a4389193fec687 Mon Sep 17 00:00:00 2001
+From: jmoellers
+Date: Fri, 7 Sep 2018 11:49:28 +0200
+Subject: [PATCH] Avoid memory leak from __zzip_parse_root_directory().
+
+---
+ zzip/zip.c | 25 ++-----------------------
+ 1 file changed, 2 insertions(+), 23 deletions(-)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index a685280..51a1a4d 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -587,34 +587,13 @@ __zzip_parse_root_directory(int fd,
+ {
+ /* If it is not assigned to *hdr_return, it will never be free()'d */
+ free(hdr0);
+- /* Make sure we don't free it again in case of error */
+- hdr0 = NULL;
+ }
+ } /* else zero (sane) entries */
+ # ifndef ZZIP_ALLOW_MODULO_ENTRIES
+- if (entries != zz_entries)
+- {
+- /* If it was assigned to *hdr_return, undo assignment */
+- if (p_reclen && hdr_return)
+- *hdr_return = NULL;
+- /* Free it, if it was not already free()'d */
+- if (hdr0 != NULL)
+- free(hdr0);
+- return ZZIP_CORRUPTED;
+- }
++ return (entries != zz_entries) ? ZZIP_CORRUPTED : 0;
+ # else
+- if (((entries & (unsigned)0xFFFF) != zz_entries)
+- {
+- /* If it was assigned to *hdr_return, undo assignment */
+- if (p_reclen && hdr_return)
+- *hdr_return = NULL;
+- /* Free it, if it was not already free()'d */
+- if (hdr0 != NULL)
+- free(hdr0);
+- return ZZIP_CORRUPTED;
+- }
++ return ((entries & (unsigned)0xFFFF) != zz_entries) ? ZZIP_CORRUPTED : 0;
+ # endif
+- return 0;
+ }
+
+ /* ------------------------- high-level interface ------------------------- */
diff --git a/SOURCES/CVE-2018-16548.part3.patch b/SOURCES/CVE-2018-16548.part3.patch
new file mode 100644
index 0000000..f2f8214
--- /dev/null
+++ b/SOURCES/CVE-2018-16548.part3.patch
@@ -0,0 +1,22 @@
+From 0e1dadb05c1473b9df2d7b8f298dab801778ef99 Mon Sep 17 00:00:00 2001
+From: jmoellers
+Date: Fri, 7 Sep 2018 13:55:35 +0200
+Subject: [PATCH] One more free() to avoid memory leak.
+
+---
+ zzip/zip.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index 51a1a4d..bc6c080 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -589,6 +589,8 @@ __zzip_parse_root_directory(int fd,
+ free(hdr0);
+ }
+ } /* else zero (sane) entries */
++ else
++ free(hdr0);
+ # ifndef ZZIP_ALLOW_MODULO_ENTRIES
+ return (entries != zz_entries) ? ZZIP_CORRUPTED : 0;
+ # else
diff --git a/SOURCES/CVE-2018-17828-singlez.patch b/SOURCES/CVE-2018-17828-singlez.patch
new file mode 100644
index 0000000..7343ab1
--- /dev/null
+++ b/SOURCES/CVE-2018-17828-singlez.patch
@@ -0,0 +1,59 @@
+diff --git a/bins/unzip-mem.c b/bins/unzip-mem.c
+index c45cb72..ff564a5 100644
+--- a/bins/unzip-mem.c
++++ b/bins/unzip-mem.c
+@@ -88,10 +88,53 @@ static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk,
+ }
+ }
+
++
++
++
++static inline void
++remove_dotdotslash(char *path)
++{
++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
++ char *dotdotslash;
++ int warned = 0;
++
++ dotdotslash = path;
++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
++ {
++ /*
++ * Remove only if at the beginning of the pathname ("../path/name")
++ * or when preceded by a slash ("path/../name"),
++ * otherwise not ("path../name..")!
++ */
++ if (dotdotslash == path || dotdotslash[-1] == '/')
++ {
++ char *src, *dst;
++ if (!warned)
++ {
++ /* Note: the first time through the pathname is still intact */
++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
++ warned = 1;
++ }
++ /* We cannot use strcpy(), as there "The strings may not overlap" */
++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
++ ;
++ }
++ else
++ dotdotslash +=3; /* skip this instance to prevent infinite loop */
++ }
++}
++
+ static void zzip_mem_entry_make(ZZIP_MEM_DISK* disk,
+ ZZIP_MEM_ENTRY* entry)
+ {
+- FILE* file = fopen (entry->zz_name, "w");
++ char name_stripped[PATH_MAX+1];
++ FILE* file;
++
++ strncpy(name_stripped, entry->zz_name, PATH_MAX);
++ name_stripped[PATH_MAX]='\0';
++ remove_dotdotslash(name_stripped);
++
++ file = fopen (name_stripped, "wb");
+ if (file) { zzip_mem_entry_pipe (disk, entry, file); fclose (file); }
+ perror (entry->zz_name);
+ if (status < EXIT_WARNINGS) status = EXIT_WARNINGS;
diff --git a/SOURCES/CVE-2018-17828.patch b/SOURCES/CVE-2018-17828.patch
new file mode 100644
index 0000000..a340295
--- /dev/null
+++ b/SOURCES/CVE-2018-17828.patch
@@ -0,0 +1,341 @@
+From 81dfa6b3e08f6934885ba5c98939587d6850d08e Mon Sep 17 00:00:00 2001
+From: Josef Moellers
+Date: Thu, 4 Oct 2018 14:21:48 +0200
+Subject: [PATCH] Fix issue #62: Remove any "../" components from pathnames of
+ extracted files. [CVE-2018-17828]
+
+---
+ bins/unzzipcat-big.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
+ bins/unzzipcat-mem.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
+ bins/unzzipcat-mix.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
+ bins/unzzipcat-zip.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 224 insertions(+), 4 deletions(-)
+
+diff --git a/bins/unzzipcat-big.c b/bins/unzzipcat-big.c
+index 982d262..88c4d65 100644
+--- a/bins/unzzipcat-big.c
++++ b/bins/unzzipcat-big.c
+@@ -53,6 +53,48 @@ static void unzzip_cat_file(FILE* disk, char* name, FILE* out)
+ }
+ }
+
++/*
++ * NAME: remove_dotdotslash
++ * PURPOSE: To remove any "../" components from the given pathname
++ * ARGUMENTS: path: path name with maybe "../" components
++ * RETURNS: Nothing, "path" is modified in-place
++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
++ * Also, "path" is not used after creating it.
++ * So modifying "path" in-place is safe to do.
++ */
++static inline void
++remove_dotdotslash(char *path)
++{
++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
++ char *dotdotslash;
++ int warned = 0;
++
++ dotdotslash = path;
++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
++ {
++ /*
++ * Remove only if at the beginning of the pathname ("../path/name")
++ * or when preceded by a slash ("path/../name"),
++ * otherwise not ("path../name..")!
++ */
++ if (dotdotslash == path || dotdotslash[-1] == '/')
++ {
++ char *src, *dst;
++ if (!warned)
++ {
++ /* Note: the first time through the pathname is still intact */
++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
++ warned = 1;
++ }
++ /* We cannot use strcpy(), as there "The strings may not overlap" */
++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
++ ;
++ }
++ else
++ dotdotslash +=3; /* skip this instance to prevent infinite loop */
++ }
++}
++
+ static void makedirs(const char* name)
+ {
+ char* p = strrchr(name, '/');
+@@ -70,6 +112,16 @@ static void makedirs(const char* name)
+
+ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ {
++ char *name_stripped;
++ FILE *fp;
++ int mustfree = 0;
++
++ if ((name_stripped = strdup(name)) != NULL)
++ {
++ remove_dotdotslash(name_stripped);
++ name = name_stripped;
++ mustfree = 1;
++ }
+ if (subdirs)
+ {
+ char* p = strrchr(name, '/');
+@@ -79,7 +131,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ free (dir_name);
+ }
+ }
+- return fopen(name, mode);
++ fp = fopen(name, mode);
++ if (mustfree)
++ free(name_stripped);
++ return fp;
+ }
+
+
+diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
+index 9bc966b..793bde8 100644
+--- a/bins/unzzipcat-mem.c
++++ b/bins/unzzipcat-mem.c
+@@ -58,6 +58,48 @@ static void unzzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out)
+ }
+ }
+
++/*
++ * NAME: remove_dotdotslash
++ * PURPOSE: To remove any "../" components from the given pathname
++ * ARGUMENTS: path: path name with maybe "../" components
++ * RETURNS: Nothing, "path" is modified in-place
++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
++ * Also, "path" is not used after creating it.
++ * So modifying "path" in-place is safe to do.
++ */
++static inline void
++remove_dotdotslash(char *path)
++{
++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
++ char *dotdotslash;
++ int warned = 0;
++
++ dotdotslash = path;
++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
++ {
++ /*
++ * Remove only if at the beginning of the pathname ("../path/name")
++ * or when preceded by a slash ("path/../name"),
++ * otherwise not ("path../name..")!
++ */
++ if (dotdotslash == path || dotdotslash[-1] == '/')
++ {
++ char *src, *dst;
++ if (!warned)
++ {
++ /* Note: the first time through the pathname is still intact */
++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
++ warned = 1;
++ }
++ /* We cannot use strcpy(), as there "The strings may not overlap" */
++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
++ ;
++ }
++ else
++ dotdotslash +=3; /* skip this instance to prevent infinite loop */
++ }
++}
++
+ static void makedirs(const char* name)
+ {
+ char* p = strrchr(name, '/');
+@@ -75,6 +117,16 @@ static void makedirs(const char* name)
+
+ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ {
++ char *name_stripped;
++ FILE *fp;
++ int mustfree = 0;
++
++ if ((name_stripped = strdup(name)) != NULL)
++ {
++ remove_dotdotslash(name_stripped);
++ name = name_stripped;
++ mustfree = 1;
++ }
+ if (subdirs)
+ {
+ char* p = strrchr(name, '/');
+@@ -84,7 +136,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ free (dir_name);
+ }
+ }
+- return fopen(name, mode);
++ fp = fopen(name, mode);
++ if (mustfree)
++ free(name_stripped);
++ return fp;
+ }
+
+ static int unzzip_cat (int argc, char ** argv, int extract)
+diff --git a/bins/unzzipcat-mix.c b/bins/unzzipcat-mix.c
+index 91c2f00..73b6ed6 100644
+--- a/bins/unzzipcat-mix.c
++++ b/bins/unzzipcat-mix.c
+@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
+ }
+ }
+
++/*
++ * NAME: remove_dotdotslash
++ * PURPOSE: To remove any "../" components from the given pathname
++ * ARGUMENTS: path: path name with maybe "../" components
++ * RETURNS: Nothing, "path" is modified in-place
++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
++ * Also, "path" is not used after creating it.
++ * So modifying "path" in-place is safe to do.
++ */
++static inline void
++remove_dotdotslash(char *path)
++{
++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
++ char *dotdotslash;
++ int warned = 0;
++
++ dotdotslash = path;
++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
++ {
++ /*
++ * Remove only if at the beginning of the pathname ("../path/name")
++ * or when preceded by a slash ("path/../name"),
++ * otherwise not ("path../name..")!
++ */
++ if (dotdotslash == path || dotdotslash[-1] == '/')
++ {
++ char *src, *dst;
++ if (!warned)
++ {
++ /* Note: the first time through the pathname is still intact */
++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
++ warned = 1;
++ }
++ /* We cannot use strcpy(), as there "The strings may not overlap" */
++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
++ ;
++ }
++ else
++ dotdotslash +=3; /* skip this instance to prevent infinite loop */
++ }
++}
++
+ static void makedirs(const char* name)
+ {
+ char* p = strrchr(name, '/');
+@@ -86,6 +128,16 @@ static void makedirs(const char* name)
+
+ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ {
++ char *name_stripped;
++ FILE *fp;
++ int mustfree = 0;
++
++ if ((name_stripped = strdup(name)) != NULL)
++ {
++ remove_dotdotslash(name_stripped);
++ name = name_stripped;
++ mustfree = 1;
++ }
+ if (subdirs)
+ {
+ char* p = strrchr(name, '/');
+@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ free (dir_name);
+ }
+ }
+- return fopen(name, mode);
++ fp = fopen(name, mode);
++ if (mustfree)
++ free(name_stripped);
++ return fp;
+ }
+
+ static int unzzip_cat (int argc, char ** argv, int extract)
+diff --git a/bins/unzzipcat-zip.c b/bins/unzzipcat-zip.c
+index 2810f85..7f7f3fa 100644
+--- a/bins/unzzipcat-zip.c
++++ b/bins/unzzipcat-zip.c
+@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
+ }
+ }
+
++/*
++ * NAME: remove_dotdotslash
++ * PURPOSE: To remove any "../" components from the given pathname
++ * ARGUMENTS: path: path name with maybe "../" components
++ * RETURNS: Nothing, "path" is modified in-place
++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it!
++ * Also, "path" is not used after creating it.
++ * So modifying "path" in-place is safe to do.
++ */
++static inline void
++remove_dotdotslash(char *path)
++{
++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
++ char *dotdotslash;
++ int warned = 0;
++
++ dotdotslash = path;
++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
++ {
++ /*
++ * Remove only if at the beginning of the pathname ("../path/name")
++ * or when preceded by a slash ("path/../name"),
++ * otherwise not ("path../name..")!
++ */
++ if (dotdotslash == path || dotdotslash[-1] == '/')
++ {
++ char *src, *dst;
++ if (!warned)
++ {
++ /* Note: the first time through the pathname is still intact */
++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
++ warned = 1;
++ }
++ /* We cannot use strcpy(), as there "The strings may not overlap" */
++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
++ ;
++ }
++ else
++ dotdotslash +=3; /* skip this instance to prevent infinite loop */
++ }
++}
++
+ static void makedirs(const char* name)
+ {
+ char* p = strrchr(name, '/');
+@@ -86,6 +128,16 @@ static void makedirs(const char* name)
+
+ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ {
++ char *name_stripped;
++ FILE *fp;
++ int mustfree = 0;
++
++ if ((name_stripped = strdup(name)) != NULL)
++ {
++ remove_dotdotslash(name_stripped);
++ name = name_stripped;
++ mustfree = 1;
++ }
+ if (subdirs)
+ {
+ char* p = strrchr(name, '/');
+@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
+ free (dir_name);
+ }
+ }
+- return fopen(name, mode);
++ fp = fopen(name, mode);
++ if (mustfree)
++ free(name_stripped);
++ return fp;
+ }
+
+ static int unzzip_cat (int argc, char ** argv, int extract)
diff --git a/SOURCES/CVE-2018-7725.patch b/SOURCES/CVE-2018-7725.patch
new file mode 100644
index 0000000..b24c8aa
--- /dev/null
+++ b/SOURCES/CVE-2018-7725.patch
@@ -0,0 +1,48 @@
+From 1ba660b3300d67b8ce9f6b96bbae0b36fa2d6b06 Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Tue, 13 Mar 2018 01:29:44 +0100
+Subject: [PATCH] check zlib space to be within buffer #39
+
+---
+ zzip/memdisk.c | 9 +++++++++
+ zzip/mmapped.c | 2 ++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/zzip/memdisk.c b/zzip/memdisk.c
+index 3de201c..8d5743d 100644
+--- a/zzip/memdisk.c
++++ b/zzip/memdisk.c
+@@ -521,11 +521,20 @@ zzip_mem_entry_fopen(ZZIP_MEM_DISK * dir, ZZIP_MEM_ENTRY * entry)
+ file->zlib.avail_in = zzip_mem_entry_csize(entry);
+ file->zlib.next_in = zzip_mem_entry_to_data(entry);
+
++ debug2("compressed size %i", (int) file->zlib.avail_in);
++ if (file->zlib.next_in + file->zlib.avail_in >= file->endbuf)
++ goto error;
++ if (file->zlib.next_in < file->buffer)
++ goto error;
++
+ if (! zzip_mem_entry_data_deflated(entry) ||
+ inflateInit2(&file->zlib, -MAX_WBITS) != Z_OK)
+ { free (file); return 0; }
+
+ return file;
++error:
++ errno = EBADMSG;
++ return NULL;
+ }
+
+ zzip__new__ ZZIP_MEM_DISK_FILE *
+diff --git a/zzip/mmapped.c b/zzip/mmapped.c
+index 920c4df..8af18f4 100644
+--- a/zzip/mmapped.c
++++ b/zzip/mmapped.c
+@@ -654,6 +654,8 @@ zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry)
+ DBG2("compressed size %i", (int) file->zlib.avail_in);
+ if (file->zlib.next_in + file->zlib.avail_in >= disk->endbuf)
+ goto error;
++ if (file->zlib.next_in < disk->buffer)
++ goto error;
+
+ if (! zzip_file_header_data_deflated(header))
+ goto error;
diff --git a/SOURCES/CVE-2018-7726.part1.patch b/SOURCES/CVE-2018-7726.part1.patch
new file mode 100644
index 0000000..563c0e1
--- /dev/null
+++ b/SOURCES/CVE-2018-7726.part1.patch
@@ -0,0 +1,31 @@
+From 8f48323c181e20b7e527b8be7229d6eb1148ec5f Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Tue, 13 Mar 2018 00:23:33 +0100
+Subject: [PATCH] check rootseek and rootsize to be positive #27
+
+---
+ zzip/zip.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index a5db9d8..6be8d7c 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -318,6 +318,8 @@ __zzip_fetch_disk_trailer(int fd, zzip_off_t filesize,
+ trailer->zz_rootseek = zzip_disk_trailer_rootseek(orig);
+ trailer->zz_rootsize = zzip_disk_trailer_rootsize(orig);
+ # endif
++ if (trailer->zz_rootseek < 0 || trailer->zz_rootsize < 0)
++ return(ZZIP_CORRUPTED); // forged value
+
+ __fixup_rootseek(offset + tail - mapped, trailer);
+ /*
+@@ -344,6 +346,8 @@ __zzip_fetch_disk_trailer(int fd, zzip_off_t filesize,
+ zzip_disk64_trailer_finalentries(orig);
+ trailer->zz_rootseek = zzip_disk64_trailer_rootseek(orig);
+ trailer->zz_rootsize = zzip_disk64_trailer_rootsize(orig);
++ if (trailer->zz_rootseek < 0 || trailer->zz_rootsize < 0)
++ return(ZZIP_CORRUPTED); // forged value
+ /*
+ * "extract data from files archived in a single zip file."
+ * So the file offsets must be within the current ZIP archive!
diff --git a/SOURCES/CVE-2018-7726.part2.patch b/SOURCES/CVE-2018-7726.part2.patch
new file mode 100644
index 0000000..574c1ce
--- /dev/null
+++ b/SOURCES/CVE-2018-7726.part2.patch
@@ -0,0 +1,40 @@
+From 19c9e4dc6c5cf92a38d0d23dbccac6993f9c41be Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Tue, 13 Mar 2018 01:50:36 +0100
+Subject: [PATCH] check rootseek after correction #41
+
+---
+ zzip/zip.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index 6be8d7c..0d79d52 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -1,4 +1,3 @@
+-
+ /*
+ * Author:
+ * Guido Draheim
+@@ -422,6 +421,9 @@ __zzip_parse_root_directory(int fd,
+ zzip_off64_t zz_rootseek = _disk_trailer_rootseek(trailer);
+ __correct_rootseek(zz_rootseek, zz_rootsize, trailer);
+
++ if (zz_entries < 0 || zz_rootseek < 0 || zz_rootseek < 0)
++ return ZZIP_CORRUPTED;
++
+ hdr0 = (struct zzip_dir_hdr *) malloc(zz_rootsize);
+ if (! hdr0)
+ return ZZIP_DIRSIZE;
+@@ -465,8 +467,9 @@ __zzip_parse_root_directory(int fd,
+ # endif
+
+ if (fd_map)
+- { d = (void*)(fd_map+zz_fd_gap+zz_offset); } /* fd_map+fd_gap==u_rootseek */
+- else
++ {
++ d = (void*)(fd_map+zz_fd_gap+zz_offset); /* fd_map+fd_gap==u_rootseek */
++ } else
+ {
+ if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0)
+ return ZZIP_DIR_SEEK;
diff --git a/SOURCES/CVE-2018-7726.part3.patch b/SOURCES/CVE-2018-7726.part3.patch
new file mode 100644
index 0000000..471b596
--- /dev/null
+++ b/SOURCES/CVE-2018-7726.part3.patch
@@ -0,0 +1,22 @@
+From feae4da1a5c92100c44ebfcbaaa895959cc0829b Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Thu, 15 Mar 2018 23:54:37 +0100
+Subject: [PATCH] fix for zz_rootsize #41
+
+---
+ zzip/zip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/zzip/zip.c b/zzip/zip.c
+index 0d79d52..14e2e06 100644
+--- a/zzip/zip.c
++++ b/zzip/zip.c
+@@ -421,7 +421,7 @@ __zzip_parse_root_directory(int fd,
+ zzip_off64_t zz_rootseek = _disk_trailer_rootseek(trailer);
+ __correct_rootseek(zz_rootseek, zz_rootsize, trailer);
+
+- if (zz_entries < 0 || zz_rootseek < 0 || zz_rootseek < 0)
++ if (zz_entries < 0 || zz_rootseek < 0 || zz_rootsize < 0)
+ return ZZIP_CORRUPTED;
+
+ hdr0 = (struct zzip_dir_hdr *) malloc(zz_rootsize);
diff --git a/SOURCES/CVE-2018-7727.patch b/SOURCES/CVE-2018-7727.patch
new file mode 100644
index 0000000..bb53479
--- /dev/null
+++ b/SOURCES/CVE-2018-7727.patch
@@ -0,0 +1,138 @@
+From 83a2da55922f67e07f22048ac9671a44cc0d35c4 Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Wed, 14 Mar 2018 07:50:44 +0100
+Subject: [PATCH] ensure disk_close to avoid mem-leak #40
+
+---
+ bins/unzzipcat-mem.c | 57 +++++++++++++++++++++++++++-------------------------
+ bins/unzzipdir-mem.c | 10 ++++-----
+ 2 files changed, 34 insertions(+), 33 deletions(-)
+
+diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
+index d13029c..9bc966b 100644
+--- a/bins/unzzipcat-mem.c
++++ b/bins/unzzipcat-mem.c
+@@ -89,7 +89,7 @@ static FILE* create_fopen(char* name, char* mode, int subdirs)
+
+ static int unzzip_cat (int argc, char ** argv, int extract)
+ {
+- int done;
++ int done = 0;
+ int argn;
+ ZZIP_MEM_DISK* disk;
+
+@@ -116,47 +116,50 @@ static int unzzip_cat (int argc, char ** argv, int extract)
+ FILE* out = stdout;
+ if (extract) out = create_fopen(name, "w", 1);
+ if (! out) {
+- if (errno != EISDIR) done = EXIT_ERRORS;
++ if (errno != EISDIR) {
++ DBG3("can not open output file %i %s", errno, strerror(errno));
++ done = EXIT_ERRORS;
++ }
+ continue;
+ }
+ unzzip_mem_disk_cat_file (disk, name, out);
+ if (extract) fclose(out);
+ }
+- return done;
+- }
+-
+- if (argc == 3 && !extract)
++ }
++ else if (argc == 3 && !extract)
+ { /* list from one spec */
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
+ {
+ unzzip_mem_entry_fprint (disk, entry, stdout);
+ }
+-
+- return 0;
+- }
+-
+- for (argn=1; argn < argc; argn++)
+- { /* list only the matching entries - each in order of commandline */
+- ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+- for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+- {
+- char* name = zzip_mem_entry_to_name (entry);
+- if (! _zzip_fnmatch (argv[argn], name,
+- FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
++ } else {
++ for (argn=1; argn < argc; argn++)
++ { /* list only the matching entries - each in order of commandline */
++ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
++ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+ {
+- FILE* out = stdout;
+- if (extract) out = create_fopen(name, "w", 1);
+- if (! out) {
+- if (errno != EISDIR) done = EXIT_ERRORS;
+- continue;
+- }
+- unzzip_mem_disk_cat_file (disk, name, out);
+- if (extract) fclose(out);
+- break; /* match loop */
++ char* name = zzip_mem_entry_to_name (entry);
++ if (! _zzip_fnmatch (argv[argn], name,
++ FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
++ {
++ FILE* out = stdout;
++ if (extract) out = create_fopen(name, "wb", 1);
++ if (! out) {
++ if (errno != EISDIR) {
++ DBG3("can not open output file %i %s", errno, strerror(errno));
++ done = EXIT_ERRORS;
++ }
++ continue;
++ }
++ unzzip_mem_disk_cat_file (disk, name, out);
++ if (extract) fclose(out);
++ break; /* match loop */
++ }
+ }
+ }
+ }
++ zzip_mem_disk_close(disk);
+ return done;
+ }
+
+diff --git a/bins/unzzipdir-mem.c b/bins/unzzipdir-mem.c
+index e54cd8d..beca788 100644
+--- a/bins/unzzipdir-mem.c
++++ b/bins/unzzipdir-mem.c
+@@ -68,10 +68,8 @@ unzzip_list (int argc, char ** argv, int verbose)
+ printf ("%lli/%lli %s %s\n", csize, usize, defl, name);
+ }
+ }
+- return 0;
+ }
+-
+- if (argc == 3)
++ else if (argc == 3)
+ { /* list from one spec */
+ ZZIP_MEM_ENTRY* entry = 0;
+ while ((entry = zzip_mem_disk_findmatch(disk, argv[2], entry, 0, 0)))
+@@ -89,9 +87,8 @@ unzzip_list (int argc, char ** argv, int verbose)
+ printf ("%lli/%lli %s %s\n", csize, usize, defl, name);
+ }
+ }
+- return 0;
+ }
+-
++ else
+ { /* list only the matching entries - in order of zip directory */
+ ZZIP_MEM_ENTRY* entry = zzip_mem_disk_findfirst(disk);
+ for (; entry ; entry = zzip_mem_disk_findnext(disk, entry))
+@@ -118,8 +115,9 @@ unzzip_list (int argc, char ** argv, int verbose)
+ }
+ }
+ }
+- return 0;
+ }
++ zzip_mem_disk_close(disk);
++ return EXIT_OK;
+ }
+
+ int
diff --git a/SOURCES/CVE-2020-18442.patch b/SOURCES/CVE-2020-18442.patch
new file mode 100644
index 0000000..3668fcd
--- /dev/null
+++ b/SOURCES/CVE-2020-18442.patch
@@ -0,0 +1,218 @@
+From ac9ae39ef419e9f0f83da1e583314d8c7cda34a6 Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:48:45 +0100
+Subject: [PATCH 1/7] #68 ssize_t return value of zzip_file_read is a signed
+ value being possibly -1
+
+---
+ bins/unzzipcat-zip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/bins/unzzipcat-zip.c b/bins/unzzipcat-zip.c
+index dd78c2b..385aeaf 100644
+--- a/bins/unzzipcat-zip.c
++++ b/bins/unzzipcat-zip.c
+@@ -34,7 +34,7 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_file_read (file, buffer, 1024)))
++ while (0 < (len = zzip_file_read (file, buffer, 1024)))
+ {
+ fwrite (buffer, 1, len, out);
+ }
+--
+2.32.0
+
+
+From 7e786544084548da7fcfcd9090d3c4e7f5777f7e Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:50:26 +0100
+Subject: [PATCH 2/7] #68 return value of zzip_mem_disk_fread is signed
+
+---
+ bins/unzip-mem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/bins/unzip-mem.c b/bins/unzip-mem.c
+index cc009f8..50eb5a6 100644
+--- a/bins/unzip-mem.c
++++ b/bins/unzip-mem.c
+@@ -81,7 +81,7 @@ static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk,
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_mem_disk_fclose (file);
+@@ -115,7 +115,7 @@ static void zzip_mem_entry_test(ZZIP_MEM_DISK* disk,
+ {
+ unsigned long crc = crc32 (0L, NULL, 0);
+ unsigned char buffer[1024]; int len;
+- while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file))) {
++ while (0 < (len = zzip_mem_disk_fread (buffer, 1024, 1, file))) {
+ crc = crc32 (crc, buffer, len);
+ }
+
+--
+2.32.0
+
+
+From d453977f59ca59c61bf59dec28dd724498828f2a Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:51:12 +0100
+Subject: [PATCH 3/7] #68 return value of zzip_entry_fread is signed
+
+---
+ bins/unzzipcat-big.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/bins/unzzipcat-big.c b/bins/unzzipcat-big.c
+index 111ef47..ecebe11 100644
+--- a/bins/unzzipcat-big.c
++++ b/bins/unzzipcat-big.c
+@@ -26,7 +26,7 @@ static void unzzip_big_entry_fprint(ZZIP_ENTRY* entry, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_entry_fread (buffer, 1024, 1, file)))
+ {
+ DBG2("entry read %i", len);
+ fwrite (buffer, len, 1, out);
+@@ -45,7 +45,7 @@ static void unzzip_cat_file(FILE* disk, char* name, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_entry_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_entry_fclose (file);
+--
+2.32.0
+
+
+From 0a9db9ded9d15fbdb63bf5cf451920d0a368c00e Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:51:56 +0100
+Subject: [PATCH 4/7] #68 return value of zzip_mem_disk_fread is signed
+
+---
+ bins/unzzipcat-mem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c
+index 6bd79b7..1b5bc22 100644
+--- a/bins/unzzipcat-mem.c
++++ b/bins/unzzipcat-mem.c
+@@ -35,7 +35,7 @@ static void unzzip_mem_entry_fprint(ZZIP_MEM_DISK* disk,
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_mem_disk_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_mem_disk_fclose (file);
+@@ -48,7 +48,7 @@ static void unzzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out)
+ if (file)
+ {
+ char buffer[1025]; int len;
+- while ((len = zzip_mem_disk_fread (buffer, 1, 1024, file)))
++ while (0 < (len = zzip_mem_disk_fread (buffer, 1, 1024, file)))
+ {
+ fwrite (buffer, 1, len, out);
+ }
+--
+2.32.0
+
+
+From a34a96fbda1e58fbec5c79f4c0b5063e031ce11d Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:52:47 +0100
+Subject: [PATCH 5/7] #68 return value of zzip_fread is signed
+
+---
+ bins/unzzipcat-mix.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/bins/unzzipcat-mix.c b/bins/unzzipcat-mix.c
+index e18987d..8f3d0b8 100644
+--- a/bins/unzzipcat-mix.c
++++ b/bins/unzzipcat-mix.c
+@@ -34,7 +34,7 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_fread (buffer, 1, 1024, file)))
++ while (0 < (len = zzip_fread (buffer, 1, 1024, file)))
+ {
+ fwrite (buffer, 1, len, out);
+ }
+--
+2.32.0
+
+
+From fa1f78abe1b08544061204019016809664f2618c Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:53:50 +0100
+Subject: [PATCH 6/7] #68 return value of zzip_entry_fread is signed
+
+---
+ bins/unzzipshow.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/bins/unzzipshow.c b/bins/unzzipshow.c
+index 9d8c2ed..5672d3b 100644
+--- a/bins/unzzipshow.c
++++ b/bins/unzzipshow.c
+@@ -22,7 +22,7 @@ static void zzip_entry_fprint(ZZIP_ENTRY* entry, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_entry_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_entry_fclose (file);
+@@ -35,7 +35,7 @@ static void zzip_cat_file(FILE* disk, char* name, FILE* out)
+ if (file)
+ {
+ char buffer[1024]; int len;
+- while ((len = zzip_entry_fread (buffer, 1024, 1, file)))
++ while (0 < (len = zzip_entry_fread (buffer, 1024, 1, file)))
+ fwrite (buffer, len, 1, out);
+
+ zzip_entry_fclose (file);
+--
+2.32.0
+
+
+From f7a6fa9f0c29aecb4c2299568ed2e6094c34aca7 Mon Sep 17 00:00:00 2001
+From: Guido Draheim
+Date: Mon, 4 Jan 2021 21:55:08 +0100
+Subject: [PATCH 7/7] #68 return value of posix read(2) is signed
+
+---
+ bins/zzipmake-zip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/bins/zzipmake-zip.c b/bins/zzipmake-zip.c
+index 8e09c31..b37877c 100644
+--- a/bins/zzipmake-zip.c
++++ b/bins/zzipmake-zip.c
+@@ -57,7 +57,7 @@ int rezzip_make (int argc, char ** argv)
+ continue;
+ }
+
+- while ((n = read (input, buf, 16)))
++ while (0 < (n = read (input, buf, 16)))
+ {
+ zzip_write (output, buf, n);
+ }
+--
+2.32.0
+
diff --git a/SOURCES/zziplib-0.13.67-multilib-32.patch b/SOURCES/zziplib-0.13.67-multilib-32.patch
new file mode 100644
index 0000000..66acd38
--- /dev/null
+++ b/SOURCES/zziplib-0.13.67-multilib-32.patch
@@ -0,0 +1,39 @@
+--- ./a/zzip/_config.h 2018-10-11 12:28:07.994739469 +0200
++++ ./b/zzip/_config.h 2018-10-11 10:30:48.000000000 +0200
+@@ -133,9 +133,11 @@
+
+ /* whether the system defaults to 32bit off_t but can do 64bit when requested
+ */
++#if __WORDSIZE == 32
+ #ifndef ZZIP_LARGEFILE_SENSITIVE
+ #define ZZIP_LARGEFILE_SENSITIVE 1
+ #endif
++#endif
+
+ /* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+@@ -185,7 +187,11 @@
+
+ /* The number of bytes in type long */
+ #ifndef ZZIP_SIZEOF_LONG
+-#define ZZIP_SIZEOF_LONG 4
++#if __WORDSIZE == 32
++#define ZZIP_SIZEOF_LONG 4
++#elif __WORDSIZE == 64
++#define ZZIP_SIZEOF_LONG 8
++#endif
+ #endif
+
+ /* The number of bytes in type short */
+@@ -221,9 +227,11 @@
+ #endif
+
+ /* Number of bits in a file offset, on hosts where this is settable. */
++#if __WORDSIZE == 32
+ #ifndef ZZIP__FILE_OFFSET_BITS
+ #define ZZIP__FILE_OFFSET_BITS 64
+ #endif
++#endif
+
+ /* Define for large files, on AIX-style hosts. */
+ /* #undef _LARGE_FILES */
diff --git a/SOURCES/zziplib-0.13.67-multilib.patch b/SOURCES/zziplib-0.13.67-multilib.patch
new file mode 100644
index 0000000..169520b
--- /dev/null
+++ b/SOURCES/zziplib-0.13.67-multilib.patch
@@ -0,0 +1,42 @@
+diff -up ./x86_64-redhat-linux-gnu/zzip/_config.h.orig ./x86_64-redhat-linux-gnu/zzip/_config.h
+--- ./x86_64-redhat-linux-gnu/zzip/_config.h.orig 2018-02-01 22:13:36.593910695 +0200
++++ ./x86_64-redhat-linux-gnu/zzip/_config.h 2018-02-01 22:15:40.341476130 +0200
+@@ -133,7 +133,11 @@
+
+ /* whether the system defaults to 32bit off_t but can do 64bit when requested
+ */
+-/* #undef LARGEFILE_SENSITIVE */
++#if __WORDSIZE == 32
++#ifndef ZZIP_LARGEFILE_SENSITIVE
++#define ZZIP_LARGEFILE_SENSITIVE 1
++#endif
++#endif
+
+ /* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+@@ -183,8 +187,12 @@
+
+ /* The number of bytes in type long */
+ #ifndef ZZIP_SIZEOF_LONG
++#if __WORDSIZE == 32
++#define ZZIP_SIZEOF_LONG 4
++#elif __WORDSIZE == 64
+ #define ZZIP_SIZEOF_LONG 8
+ #endif
++#endif
+
+ /* The number of bytes in type short */
+ #ifndef ZZIP_SIZEOF_SHORT
+@@ -219,7 +227,11 @@
+ #endif
+
+ /* Number of bits in a file offset, on hosts where this is settable. */
+-/* #undef _FILE_OFFSET_BITS */
++#if __WORDSIZE == 32
++#ifndef ZZIP__FILE_OFFSET_BITS
++#define ZZIP__FILE_OFFSET_BITS 64
++#endif
++#endif
+
+ /* Define for large files, on AIX-style hosts. */
+ /* #undef _LARGE_FILES */
diff --git a/SPECS/zziplib.spec b/SPECS/zziplib.spec
new file mode 100644
index 0000000..29ce6fc
--- /dev/null
+++ b/SPECS/zziplib.spec
@@ -0,0 +1,299 @@
+Summary: Lightweight library to easily extract data from zip files
+Name: zziplib
+Version: 0.13.68
+Release: 9%{?dist}
+License: LGPLv2+ or MPLv1.1
+Group: Applications/Archiving
+URL: http://zziplib.sourceforge.net/
+Source: https://github.com/gdraheim/zziplib/archive/v%{version}.tar.gz
+
+Patch100: zziplib-0.13.67-multilib.patch
+Patch101: zziplib-0.13.67-multilib-32.patch
+
+Patch1: 0001-FIX-port-documentation-scripts-to-python3.patch
+Patch2: CVE-2018-7725.patch
+#part1 also fixes #1545818
+Patch3: CVE-2018-7726.part1.patch
+Patch4: CVE-2018-7726.part2.patch
+Patch5: CVE-2018-7726.part3.patch
+Patch6: CVE-2018-7727.patch
+
+Patch7: CVE-2018-16548.part1.patch
+Patch8: CVE-2018-16548.part2.patch
+Patch9: CVE-2018-16548.part3.patch
+
+Patch10: CVE-2018-17828.patch
+Patch11: CVE-2018-17828-singlez.patch
+
+Patch12: CVE-2020-18442.patch
+
+BuildRequires: perl-interpreter
+BuildRequires: python3-devel
+BuildRequires: python3-six
+BuildRequires: zip
+BuildRequires: xmlto
+BuildRequires: zlib-devel
+BuildRequires: SDL-devel
+BuildRequires: pkgconfig
+#BuildRequires: autoconf
+#BuildRequires: automake
+
+%description
+The zziplib library is intentionally lightweight, it offers the ability to
+easily extract data from files archived in a single zip file. Applications
+can bundle files into a single zip archive and access them. The implementation
+is based only on the (free) subset of compression with the zlib algorithm
+which is actually used by the zip/unzip tools.
+
+%package utils
+Summary: Utilities for the zziplib library
+Group: Applications/Archiving
+Requires: %{name}%{?_isa} = %{version}-%{release}
+
+%description utils
+The zziplib library is intentionally lightweight, it offers the ability to
+easily extract data from files archived in a single zip file. Applications
+can bundle files into a single zip archive and access them. The implementation
+is based only on the (free) subset of compression with the zlib algorithm
+which is actually used by the zip/unzip tools.
+
+This packages contains all the utilities that come with the zziplib library.
+
+%package devel
+Summary: Development files for the zziplib library
+Group: Development/Libraries
+Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: pkgconfig
+Requires: zlib-devel
+Requires: SDL-devel
+
+%description devel
+The zziplib library is intentionally lightweight, it offers the ability to
+easily extract data from files archived in a single zip file. Applications
+can bundle files into a single zip archive and access them. The implementation
+is based only on the (free) subset of compression with the zlib algorithm
+which is actually used by the zip/unzip tools.
+
+This package contains files required to build applications that will use the
+zziplib library.
+
+%prep
+%setup -q
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+
+pathfix.py -i %{__python3} -pn docs
+
+%build
+export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"
+%configure \
+ --disable-static \
+ --enable-sdl \
+ --enable-frame-pointer \
+ --enable-builddir=_builddir
+# Remove rpath on 64bit archs
+sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' */libtool
+sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' */libtool
+# Only patch generated _config.h on non-i686 and armv7hl
+# These platforms have a correct _config.h already
+cd _builddir
+%ifarch i686 armv7hl
+%apply_patch %{PATCH101} -p2
+%endif
+%ifnarch i686 armv7hl
+%apply_patch %{PATCH100} -p2
+%endif
+cd ..
+
+%{__make} %{?_smp_mflags}
+
+
+%install
+make install DESTDIR=%{buildroot}
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%doc docs/COPYING* ChangeLog README TODO
+%{_libdir}/*.so.*
+
+%files utils
+%{_bindir}/*
+
+%files devel
+%doc docs/README.SDL docs/*.htm docs/*.html
+%{_includedir}/*
+%exclude %{_libdir}/*.la
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/*.pc
+%{_datadir}/aclocal/*.m4
+%{_mandir}/man3/*
+
+%changelog
+* Mon Aug 02 2021 Jakub Martisko - 0.13.68-9
+- Fix CVE-2020-18442
+- Resolves: CVE-2020-18442
+
+* Tue Oct 16 2018 Jakub Martisko - 0.13.68-8
+- Fix CVE-2018-17828 in the "single z" binaries
+- Resolves: #1772447
+
+* Tue Oct 16 2018 Jakub Martisko - 0.13.68-7
+- Fix CVE-2018-17828
+- Resolves: #1635890
+
+* Thu Oct 11 2018 Jakub Martisko - 0.13.68-6
+- Fix multilib regression by adding a 32bit version of the multilib patch
+- Properly bump the release number in the previous changelog message
+- Resolves: #1638337
+
+* Thu Oct 04 2018 Jakub Martisko - 0.13.68-5
+- Fix memory leak caused by the CVE-2018-16548
+- Resolves: #1626202
+
+* Mon Aug 13 2018 Jakub Martisko - 0.13.68-4
+- Change the build dependency to python-devel and use the pathfix.py script
+- Related: 1592262
+
+* Sat Jul 28 2018 Jakub Martisko - 0.13.68-3
+- Fix CVEs 2018-7725, 2018-7726, 2018-7727, 2018-6484, 2018-6869
+- Resolves: 1555082
+- Resolves: 1545818
+
+* Tue Jul 03 2018 Jakub Martisko - 0.13.68-2
+- Port documentation generating scripts to Python 3
+- Include both docs/*.htm and docs/*html files
+
+* Wed Feb 14 2018 Alexander Bokovoy - 0.13.68-1
+- 0.13.68
+- Fixes: #1543942 (CVE-2018-6484)
+
+* Fri Feb 09 2018 Fedora Release Engineering - 0.13.67-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Thu Feb 01 2018 Alexander Bokovoy - 0.13.67-1
+- Update release
+- CVE-2018-6381
+
+* Thu Aug 03 2017 Fedora Release Engineering - 0.13.62-10
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Thu Jul 27 2017 Fedora Release Engineering - 0.13.62-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Sat Feb 11 2017 Fedora Release Engineering - 0.13.62-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Fri Feb 05 2016 Fedora Release Engineering - 0.13.62-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Fri Jun 19 2015 Fedora Release Engineering - 0.13.62-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Mon Aug 18 2014 Fedora Release Engineering - 0.13.62-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sat Jun 07 2014 Fedora Release Engineering - 0.13.62-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Sun Aug 04 2013 Fedora Release Engineering - 0.13.62-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Wed Jan 30 2013 Jindrich Novy 0.13.62-2
+- rebuild with -fno-strict-aliasing
+
+* Wed Oct 10 2012 Matthias Saou 0.13.62-1
+- Update to 0.13.62.
+- Remove no longer needed -Wl patch.
+
+* Sun Jul 22 2012 Fedora Release Engineering - 0.13.60-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Thu Mar 8 2012 Tom Callaway - 0.13.60-1
+- update to 0.13.60
+
+* Sat Jan 14 2012 Fedora Release Engineering - 0.13.59-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Feb 08 2011 Fedora Release Engineering - 0.13.59-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Thu Dec 9 2010 Hans de Goede 0.13.59-2
+- Fix broken zzip/_config.h which causes apps using zziplib to fail to compile
+
+* Sat Dec 4 2010 Matthias Saou 0.13.59-1
+- Update to 0.13.59.
+- Remove no longer needed 'open' patch.
+- Rebase the multilib patch, still required.
+- Re-enable _smp_mflags, build works again with it apparently.
+
+* Mon Jul 27 2009 Fedora Release Engineering - 0.13.49-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Feb 25 2009 Fedora Release Engineering - 0.13.49-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Mon Dec 22 2008 Matthias Saou 0.13.49-6
+- Patch _config.h to make it identical for 32bit and 64bit archs (#343521).
+
+* Tue Feb 19 2008 Fedora Release Engineering
+- Autorebuild for GCC 4.3
+
+* Wed Aug 8 2007 Matthias Saou 0.13.49-4
+- Include patch to fix fd.open calls with recent glibc.
+- Disable _smp_mflags since the docs fail to build.
+
+* Fri Aug 3 2007 Matthias Saou 0.13.49-3
+- Update License field.
+
+* Tue Jun 19 2007 Matthias Saou 0.13.49-2
+- Disable static lib build instead of excluding it later.
+- Remove rpath on 64bit archs.
+- Switch to using DESTDIR install method.
+
+* Mon Mar 26 2007 Matthias Saou 0.13.49-1
+- Update to 0.13.49 to fix CVE-2007-1614 (rhbz #233700).
+- Include new man3 pages to the devel sub-package.
+
+* Mon Aug 28 2006 Matthias Saou 0.13.47-1
+- Update to 0.13.47.
+- FC6 rebuild.
+
+* Mon Jul 24 2006 Matthias Saou 0.13.45-3
+- Split off -utils sub-package (#199467). Could have been plain "zzip"?
+- Have sub-packages require exact release too.
+- Build require automake to make the aclocal-1.9 check happy.
+- Use --enable-frame-pointer otherwise -g gets removed from the CFLAGS.
+
+* Mon Mar 6 2006 Matthias Saou 0.13.45-2
+- FC5 rebuild.
+
+* Thu Feb 9 2006 Matthias Saou 0.13.45-1
+- Update to 0.13.45.
+- Exclude static library.
+
+* Sun May 22 2005 Jeremy Katz - 0.13.38-2
+- rebuild on all arches
+
+* Tue Apr 5 2005 Matthias Saou 0.13.38-1
+- Update to 0.13.38, fixes gcc4 compile issues (Adrian Reber).
+
+* Tue Nov 16 2004 Matthias Saou 0.13.36-2
+- Bump release to provide Extras upgrade path.
+
+* Tue Jun 8 2004 Matthias Saou 0.13.36-1
+- Initial RPM release.
+