commit c19a2646b6389a8b0c3671b107c30c65923b7e72 Author: MSVSphere Packaging Team Date: Fri Mar 29 16:39:54 2024 +0300 import zziplib-0.13.68-12.el8 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) (\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, "" ++ print("<"+H+" name=\""+name+"\">", end=' ', file=F) ++ print(str(func.dict()[H]), end=' ', file=F) ++ print("", 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, "" ++ print(text, file=fd) ++ print("", 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/CVE-2020-18770.patch b/SOURCES/CVE-2020-18770.patch new file mode 100644 index 0000000..e4c7880 --- /dev/null +++ b/SOURCES/CVE-2020-18770.patch @@ -0,0 +1,30 @@ +From 18c6c043bd7d8f139f30e9c7749013115d5fc5b7 Mon Sep 17 00:00:00 2001 +From: Valentin Lefebvre +Date: Wed, 20 Sep 2023 12:04:56 +0200 +Subject: [PATCH] mmappend.c: Avoid invalid access for header entry + +* zzip_disk_entry_to_file_header checking the pointer by substraction + instead of addition where it could lead to an invalid access memory. +* CVE-2020-18770 + +Signed-off-by: Valentin Lefebvre +--- + zzip/mmapped.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/zzip/mmapped.c b/zzip/mmapped.c +index 2071882..beb094d 100644 +--- a/zzip/mmapped.c ++++ b/zzip/mmapped.c +@@ -275,8 +275,9 @@ zzip_disk_entry_to_data(ZZIP_DISK * disk, struct zzip_disk_entry * entry) + struct zzip_file_header * + zzip_disk_entry_to_file_header(ZZIP_DISK * disk, struct zzip_disk_entry *entry) + { +- zzip_byte_t *const ptr = disk->buffer + zzip_disk_entry_fileoffset(entry); +- if (disk->buffer > ptr || ptr >= disk->endbuf) ++ zzip_off_t off = zzip_disk_entry_fileoffset(entry); ++ zzip_byte_t *const ptr = disk->buffer + off; ++ if (disk->buffer > ptr || disk->buffer >= disk->endbuf - off) + { + errno = EBADMSG; + return 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..cc6eac0 --- /dev/null +++ b/SPECS/zziplib.spec @@ -0,0 +1,315 @@ +Summary: Lightweight library to easily extract data from zip files +Name: zziplib +Version: 0.13.68 +Release: 12%{?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 +Patch13: CVE-2020-18770.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 +%patch13 -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 \ + ac_cv_path_PYTHON=%__python3 + +# 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 +* Tue Feb 06 2024 Jakub Martisko - 0.13.68-12 +- Add the gating tests from the 8.8.0 branch + Resolves: RHEL-24429 + +* Sat Jan 27 2024 Jakub Martisko - 0.13.68-11 +- Use %__python3 macro during the config phase (used for doc generation) + Resolves: RHEL-22880 + +* Wed Jan 24 2024 Jakub Martisko - 0.13.68-10 +- Fix CVE-2020-18770 + Resolves: RHEL-14966 + +* 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. +