Compare commits

...

No commits in common. "c8" and "c9s" have entirely different histories.
c8 ... c9s

36 changed files with 1209 additions and 1832 deletions

12
.gitignore vendored
View File

@ -1 +1,11 @@
SOURCES/v0.13.68.tar.gz
zziplib-0.13.49.tar.bz2
/zziplib-0.13.59.tar.bz2
/zziplib-0.13.60.tar.bz2
/zziplib-0.13.62.tar.bz2
/v0.13.67.tar.gz
/v0.13.68.tar.gz
/v0.13.69.tar.gz
/v0.13.71.tar.gz
/v0.13.71-pruned.tar.gz
/match.py
/options.py

View File

@ -1 +0,0 @@
bf62bf6138a7a5bddbad41d6c5dbb169e1528110 SOURCES/v0.13.68.tar.gz

30
CVE-2020-18770.patch Normal file
View File

@ -0,0 +1,30 @@
From 18c6c043bd7d8f139f30e9c7749013115d5fc5b7 Mon Sep 17 00:00:00 2001
From: Valentin Lefebvre <valentin.lefebvre@suse.com>
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 <valentin.lefebvre@suse.com>
---
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;

View File

@ -1,850 +0,0 @@
From f04dd2918b15853e866d3941b72005696c8c3b8f Mon Sep 17 00:00:00 2001
From: Jakub Martisko <jamartis@redhat.com>
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):
"<para>" : "<p>", "</para>" : "</p>" ,
"<function>" : "<link>", "</function>" : "</link>" }
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, "&", "&amp;")
+ return text.replace("&", "&amp;")
def cdata31(text):
- return string.replace(string.replace(text, "<","&lt;"), ">","&gt;")
+ return text.replace(text, "<","&lt;").replace( ">","&gt;")
def cdata3(text):
return cdata31(cdata1(text))
def cdata43(text):
- return string.replace(text,"\"", "&quot;")
+ return text.replace("\"", "&quot;")
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*) <br\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 += "<tr valign=\"top\">\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, '<reference><title>Manual Pages</title>'
+ print(doctype, '<reference><title>Manual Pages</title>', 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<!-- _______ "+page.id+" _______ -->",
- print >> F, page.refentry_text()
+ print("\n<!-- _______ "+page.id+" _______ -->", end=' ', file=F)
+ print(page.refentry_text(), file=F)
#od
- print >> F, "\n",'</reference>',"\n"
+ print("\n",'</reference>',"\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, "<fn id=\""+name+"\">"+"<!-- FOR \""+name+"\" -->\n"
+ print("<fn id=\""+name+"\">"+"<!-- FOR \""+name+"\" -->\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, "</fn><!-- END \""+name+"\" -->\n\n";
+ print("</fn><!-- END \""+name+"\" -->\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 "<!DOCTYPE "+rootnode+self.docbook_dtd+">"
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>'+title+'</title>'
+ print("<"+self.rootnode+'><title>'+title+'</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 = ("<code><b><function>"+namespec+"</function></b>"
+callspec+" : "+prespec+"</code>")
- except Exception, e:
+ except Exception as e:
pass
try:
extraline = ""
@@ -56,7 +58,7 @@ class FunctionListHtmlPage:
'<em><small>'+filename+'</small></em>'+
'</td></table>')
body_text = extraline + body_text
- except Exception, e:
+ except Exception as e:
pass
def link(text):
return (text & Match("<function>(\w*)</function>")
@@ -102,7 +104,7 @@ class FunctionListHtmlPage:
text &= (Match("(?s)<link>(\w+)</link>")
>> (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)<link>([^<>]*)</link>")
>> "<code>\\1</code>")
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 <reference> list of <refentry> 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 "&nbsp;"
+ except Exception as e: print("HtmlDocument/text", e); return "&nbsp;"
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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt")
@@ -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

View File

@ -1,71 +0,0 @@
From 9411bde3e4a70a81ff3ffd256b71927b2d90dcbb Mon Sep 17 00:00:00 2001
From: jmoellers <josef.moellers@suse.com>
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 ------------------------- */

View File

@ -1,50 +0,0 @@
From d2e5d5c53212e54a97ad64b793a4389193fec687 Mon Sep 17 00:00:00 2001
From: jmoellers <josef.moellers@suse.com>
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 ------------------------- */

View File

@ -1,22 +0,0 @@
From 0e1dadb05c1473b9df2d7b8f298dab801778ef99 Mon Sep 17 00:00:00 2001
From: jmoellers <josef.moellers@suse.com>
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

View File

@ -1,59 +0,0 @@
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;

View File

@ -1,341 +0,0 @@
From 81dfa6b3e08f6934885ba5c98939587d6850d08e Mon Sep 17 00:00:00 2001
From: Josef Moellers <jmoellers@suse.de>
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)

View File

@ -1,48 +0,0 @@
From 1ba660b3300d67b8ce9f6b96bbae0b36fa2d6b06 Mon Sep 17 00:00:00 2001
From: Guido Draheim <guidod@gmx.de>
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;

View File

@ -1,31 +0,0 @@
From 8f48323c181e20b7e527b8be7229d6eb1148ec5f Mon Sep 17 00:00:00 2001
From: Guido Draheim <guidod@gmx.de>
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!

View File

@ -1,40 +0,0 @@
From 19c9e4dc6c5cf92a38d0d23dbccac6993f9c41be Mon Sep 17 00:00:00 2001
From: Guido Draheim <guidod@gmx.de>
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 <guidod@gmx.de>
@@ -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;

View File

@ -1,22 +0,0 @@
From feae4da1a5c92100c44ebfcbaaa895959cc0829b Mon Sep 17 00:00:00 2001
From: Guido Draheim <guidod@gmx.de>
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);

View File

@ -1,138 +0,0 @@
From 83a2da55922f67e07f22048ac9671a44cc0d35c4 Mon Sep 17 00:00:00 2001
From: Guido Draheim <guidod@gmx.de>
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

View File

@ -1,39 +0,0 @@
--- ./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 */

View File

@ -1,42 +0,0 @@
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 */

6
gating.yaml Normal file
View File

@ -0,0 +1,6 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

29
multilib-32.patch Normal file
View File

@ -0,0 +1,29 @@
--- ./a/zzip/_config.h 2021-07-21 14:18:09.000000000 +0200
+++ ./b/zzip/_config.h 2021-07-21 14:46:24.037432969 +0200
@@ -138,9 +138,12 @@
/* 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
+/* #undef LARGEFILE_SENSITIVE */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#ifndef ZZIP_LT_OBJDIR
@@ -227,9 +230,13 @@
#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
+/* #undef _FILE_OFFSET_BITS */
+
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */

29
multilib-64.patch Normal file
View File

@ -0,0 +1,29 @@
--- ./a/zzip/_config.h 2021-07-21 14:18:14.000000000 +0200
+++ ./b/zzip/_config.h 2021-07-21 14:46:24.037432969 +0200
@@ -138,6 +138,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
/* #undef LARGEFILE_SENSITIVE */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
@@ -225,8 +230,14 @@
#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
/* #undef _FILE_OFFSET_BITS */
+
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */

3
sources Normal file
View File

@ -0,0 +1,3 @@
SHA512 (v0.13.71-pruned.tar.gz) = a121e2d6bd545350623571055559575bad8ef620ae66cd1bf8112c089b06cd5a293799edc68171dfb64798328f1208b1fdeb6d0a208b3e682e03a578ae092570
SHA512 (match.py) = cd76328f468dd96d2d453bfc9ae66b6d560f9caa59b08a467ff71b862123bc50191d71d3af2fed837bab780cd3d6403b2053871249b01227ef072b4e3fe938d3
SHA512 (options.py) = 47a581611a6dfca92013ae8029bdb48ab0c711ca5e2981a0fabc6fa9e59739b9bfbe8df2d1ac5b15e20e238e15516588c0dd13f7375d6706e22456e54084e610

55
tests/gating/all.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
# Copyright (C) 2019 Jakub Martisko <jamartis at redhat dot com>
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
passed=0
subtests=(build)
total=${#subtests[@]}
skipped=0
for subtest in ${subtests[@]}
do
#tests to be skipped
if [ $subtest == "foo" ]
then
((skipped++))
continue
fi
pushd $subtest >/dev/null
./test.sh
result=$?
echo "Test $subtest result: $result"
if [ "$result" == "0" ]
then
((passed++))
fi
popd >/dev/null
done
echo "Passed $passed/$total tests"
echo "Skipped $skipped/$total tests"
[[ $total == $((passed + skipped)) ]] || exit 1

View File

@ -0,0 +1,96 @@
#ifndef __ZZIP_INTERNAL_DEBUG_H
#define __ZZIP_INTERNAL_DEBUG_H
#include <zzip/conf.h>
#include "__hints.h"
/* perhaps want to show on syslog(3) ?? */
#ifdef DEBUG
#include <stdio.h>
#define MSG1(X1) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
); } ZZIP_END1
#define MSG2(X1,X2) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
,X2);} ZZIP_END1
#define MSG3(X1,X2,X3) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
,X2,X3); } ZZIP_END1
#define MSG4(X1,X2,X3,X4) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
,X2,X3,X4); } ZZIP_END1
#define MSG5(X1,X2,X3,X4,X5) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
,X2,X3,X4,X5); } ZZIP_END1
#define MSG6(X1,X2,X3,X4,X5,X6) ZZIP_FOR1 { \
fprintf(stderr,"\n%s:%i:"X1"\n", ZZIP_FUNC,__LINE__ \
,X2,X3,X4,X5,X6); } ZZIP_END1
#else
#define MSG1(X1) {}
#define MSG2(X1,X2) {}
#define MSG3(X1,X2,X3) {}
#define MSG4(X1,X2,X3,X4) {}
#define MSG5(X1,X2,X3,X4,X5) {}
#define MSG6(X1,X2,X3,X4,X5,X6) {}
#endif
#define DBG1(X1) MSG1("DEBUG: " X1)
#define DBG2(X1,X2) MSG2("DEBUG: " X1,X2)
#define DBG3(X1,X2,X3) MSG3("DEBUG: " X1,X2,X3)
#define DBG4(X1,X2,X3,X4) MSG4("DEBUG: " X1,X2,X3,X4)
#define DBG5(X1,X2,X3,X4,X5) MSG5("DEBUG: " X1,X2,X3,X4,X5)
#define DBG6(X1,X2,X3,X4,X5,X6) MSG6("DEBUG: " X1,X2,X3,X4,X5,X6)
#define HINT1(X1) MSG1("HINT: " X1)
#define HINT2(X1,X2) MSG2("HINT: " X1,X2)
#define HINT3(X1,X2,X3) MSG3("HINT: " X1,X2,X3)
#define HINT4(X1,X2,X3,X4) MSG4("HINT: " X1,X2,X3,X4)
#define HINT5(X1,X2,X3,X4,X5) MSG5("HINT: " X1,X2,X3,X4,X5)
#define HINT6(X1,X2,X3,X4,X5,X6) MSG6("HINT: " X1,X2,X3,X4,X5,X6)
#define NOTE1(X1) MSG1("NOTE: " X1)
#define NOTE2(X1,X2) MSG2("NOTE: " X1,X2)
#define NOTE3(X1,X2,X3) MSG3("NOTE: " X1,X2,X3)
#define NOTE4(X1,X2,X3,X4) MSG4("NOTE: " X1,X2,X3,X4)
#define NOTE5(X1,X2,X3,X4,X5) MSG5("NOTE: " X1,X2,X3,X4,X5)
#define NOTE6(X1,X2,X3,X4,X5,X6) MSG6("NOTE: " X1,X2,X3,X4,X5,X6)
#define WARN1(X1) MSG1("WARN: " X1)
#define WARN2(X1,X2) MSG2("WARN: " X1,X2)
#define WARN3(X1,X2,X3) MSG3("WARN: " X1,X2,X3)
#define WARN4(X1,X2,X3,X4) MSG4("WARN: " X1,X2,X3,X4)
#define WARN5(X1,X2,X3,X4,X5) MSG5("WARN: " X1,X2,X3,X4,X5)
#define WARN6(X1,X2,X3,X4,X5,X6) MSG6("WARN: " X1,X2,X3,X4,X5,X6)
#define FAIL1(X1) MSG1("FAIL: " X1)
#define FAIL2(X1,X2) MSG2("FAIL: " X1,X2)
#define FAIL3(X1,X2,X3) MSG3("FAIL: " X1,X2,X3)
#define FAIL4(X1,X2,X3,X4) MSG4("FAIL: " X1,X2,X3,X4)
#define FAIL5(X1,X2,X3,X4,X5) MSG5("FAIL: " X1,X2,X3,X4,X5)
#define FAIL6(X1,X2,X3,X4,X5,X6) MSG6("FAIL: " X1,X2,X3,X4,X5,X6)
#ifdef DEBUG
_zzip_inline static void zzip_debug_xbuf (unsigned char* p, int l)
/* ZZIP_GNUC_UNUSED */
{
# define q(a) ((a&0x7F)<32?32:(a&0x7F))
while (l > 0)
{
fprintf (stderr,
"%02x %02x %02x %02x "
"%02x %02x %02x %02x "
"%c%c%c%c %c%c%c%c\n",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
q(p[0]), q(p[1]), q(p[2]), q(p[3]),
q(p[4]), q(p[5]), q(p[6]), q(p[7]));
p += 8; l -= 8;
}
# undef q
}
#endif
#endif

View File

@ -0,0 +1,32 @@
#ifndef __ZZIP_INTERNAL_FNMATCH_H
#define __ZZIP_INTERNAL_FNMATCH_H
/** included by fseeko.c, mmapped.c, memdisk.c */
#include <zzip/conf.h>
#include <stdio.h>
#include <string.h>
#ifdef ZZIP_HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
#ifdef ZZIP_HAVE_FNMATCH_H
#define _zzip_fnmatch fnmatch
# ifdef FNM_CASEFOLD
# define _zzip_FNM_CASEFOLD FNM_CASEFOLD
# else
# define _zzip_FNM_CASEFOLD 0
# endif
#else
# define _zzip_FNM_CASEFOLD 0
/* if your system does not have fnmatch, we fall back to strcmp: */
static int _zzip_fnmatch(char* pattern, char* string, int flags)
{
# ifdef DBG2
DBG1("<zzip:mmapped:strcmp>");
# endif
return strcmp (pattern, string);
}
#endif
#endif

View File

@ -0,0 +1,195 @@
#ifndef __ZZIP_INTERNAL_HINTS_H
#define __ZZIP_INTERNAL_HINTS_H
#include <zzip/conf.h>
#ifndef ZZIP_GNUC_ATLEAST
# if defined __GNUC__ && defined __GNUC_MINOR__
# define ZZIP_GNUC_ATLEAST(_M_,_N_) \
((__GNUC__ << 10) + __GNUC_MINOR__ >= ((_M_) << 10) + (_N_))
# elif defined __GNUC__
# define ZZIP_GNUC_ATLEAST(_M_,_N_) \
((__GNUC__ << 10) >= ((_M_) << 10))
# else
# define ZZIP_GNUC_ATLEAST(_M_, _N_) 0
# endif
#endif
#ifndef ZZIP_GNUC_EXTENSION
# if ZZIP_GNUC_ATLEAST(2,8)
# define ZZIP_GNUC_EXTENSION __extension__
# else
# define ZZIP_GNUC_EXTENSION
# endif
#endif
/* func has no side effects, return value depends only on params and globals */
#ifndef ZZIP_GNUC_PURE
# if ZZIP_GNUC_ATLEAST(2,8)
# define ZZIP_GNUC_PURE __attribute__((__pure__))
# else
# define ZZIP_GNUC_PURE
# endif
#endif
/* func has no side effects, return value depends only on params */
#ifndef ZZIP_GNUC_CONST
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_CONST __attribute__((__const__))
# else
# define ZZIP_GNUC_CONST
# endif
#endif
/* typename / variable / function possibly unused */
#ifndef ZZIP_GNUC_UNUSED
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_UNUSED __attribute__((__unused__))
# else
# define ZZIP_GNUC_UNUSED
# endif
#endif
/* obvious. btw, a noreturn-func should return void */
#ifndef ZZIP_GNUC_NORETURN
# if ZZIP_GNUC_ATLEAST(2,5)
# define ZZIP_GNUC_NORETURN __attribute__((__noreturn__))
# else
# define ZZIP_GNUC_NORETURN
# endif
#endif
/* omit function from profiling with -finstrument-functions */
#ifndef ZZIP_GNUC_NO_INSTRUMENT
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_NO_INSTRUMENT __attribute__((__no_instrument_function__))
# else
# define ZZIP_GNUC_NO_INSTRUMENT
# endif
#endif
/* all pointer args must not be null, and allow optimiztons based on the fact*/
#ifndef ZZIP_GNUC_NONNULL
# if ZZIP_GNUC_ATLEAST(3,1)
# define ZZIP_GNUC_NONNULL __attribute__((nonnull))
# else
# define ZZIP_GNUC_NONNULL
# endif
#endif
/* the function can not throw - the libc function are usually nothrow */
#ifndef ZZIP_GNUC_NOTHROW
# if ZZIP_GNUC_ATLEAST(3,2)
# define ZZIP_GNUC_NOTHROW __attribute__((nothrow))
# else
# define ZZIP_GNUC_NOTHROW
# endif
#endif
/* typename / function / variable is obsolete but still listed in headers */
#ifndef ZZIP_GNUC_DEPRECATED
# if ZZIP_GNUC_ATLEAST(3,1)
# define ZZIP_GNUC_DEPRECATED __attribute__((deprecated))
# else
# define ZZIP_GNUC_DEPRECATED
# endif
#endif
/* resolve references to this function during pre-linking the library */
#ifndef ZZIP_GNUC_LIB_PROTECTED
# if ZZIP_GNUC_ATLEAST(3,1)
# define ZZIP_GNUC_LIB_PROTECTED __attribute__((visiblity("protected")))
# else
# define ZZIP_GNUC_LIB_PROTECTED
# endif
#endif
/* func shall only be usable within the same lib (so, no entry in lib symtab)*/
#ifndef ZZIP_GNUC_LIB_PRIVATE
# if ZZIP_GNUC_ATLEAST(3,1)
# define ZZIP_GNUC_LIB_PRIVATE __attribute__((visiblity("hidden")))
# else
# define ZZIP_GNUC_LIB_PRIVATE
# endif
#endif
/* ... and not even passed as a function pointer reference to outside the lib*/
#ifndef ZZIP_GNUC_LIB_INTERNAL
# if ZZIP_GNUC_ATLEAST(3,1)
# define ZZIP_GNUC_LIB_INTERNAL __attribute__((visiblity("internal")))
# else
# define ZZIP_GNUC_LIB_INTERNAL
# endif
#endif
#ifndef ZZIP_GNUC_FORMAT
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_FORMAT(_X_) __attribute__((__format_arg__(_X_)))
# else
# define ZZIP_GNUC_FORMAT(_X_)
# endif
#endif
#ifndef ZZIP_GNUC_SCANF
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_SCANF(_S_,_X_) __attribute__((__scanf__(_S_,_X_)))
# else
# define ZZIP_GNUC_SCANF(_S_,_X_)
# endif
#endif
#ifndef ZZIP_GNUC_PRINTF
# if ZZIP_GNUC_ATLEAST(2,4)
# define ZZIP_GNUC_PRINTF(_S_,_X_) __attribute__((__printf__(_S_,_X_)))
# else
# define ZZIP_GNUC_PRINTF(_S_,_X_)
# endif
#endif
#ifdef __GNUC__
#define ZZIP_GNUC_PACKED __attribute__((packed))
#else
#define ZZIP_GNUC_PACKED
#endif
#ifndef ZZIP_FUNCTION
# if ZZIP_GNUC_ATLEAST(2,6)
# define ZZIP_FUNC __FUNCTION__
# define ZZIP_FUNCTION __FUNCTION__
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
# define ZZIP_FUNC __func__
# define ZZIP_FUNCTION ""
# else
# define ZZIP_FUNC 0
# define ZZIP_FUNCTION ""
# endif
#endif
#ifndef ZZIP_STRING
#define ZZIP_STRING(_X_) ZZIP_STRING_(_X_)
#define ZZIP_STRING_(_Y_) #_Y_
#endif
#ifndef ZZIP_DIM
#define ZZIP_DIM(_A_) (sizeof(_A_) / sizeof ((_A_)[0]))
#endif
#if !(defined ZZIP_FOR1 && defined ZZIP_END1)
# if defined sun || defined __sun__
# define ZZIP_FOR1 if (1)
# define ZZIP_END1 else (void)0
# else
# define ZZIP_FOR1 do
# define ZZIP_END1 while (0)
# endif
#endif
#ifndef ZZIP_BRANCH_OVER
# if ZZIP_GNUC_ATLEAST(2,96)
# define ZZIP_BRANCH_OVER(_X_) __builtin_expect((_X_),0)
# else
# define ZZIP_BRANCH_OVER(_X_) (_X_)
# endif
#endif
#endif

View File

@ -0,0 +1,12 @@
#ifndef __ZZIP_INTERNAL_MKDIR_H
#define __ZZIP_INTERNAL_MKDIR_H
#include <zzip/conf.h>
# ifdef ZZIP_HAVE_DIRECT_H
# define _zzip_mkdir(a,b) mkdir(a)
# else
# define _zzip_mkdir mkdir
# endif
#endif

View File

@ -0,0 +1,67 @@
#ifndef __ZZIP_INTERNAL_STRING_H
#define __ZZIP_INTERNAL_STRING_H
#ifdef __linux__
#define _GNU_SOURCE _glibc_developers_are_idiots_to_call_strndup_gnu_specific_
#endif
#include <zzip/conf.h>
#if defined ZZIP_HAVE_STRING_H
#include <string.h>
#elif defined ZZIP_HAVE_STRINGS_H
#include <strings.h>
#endif
#if defined ZZIP_HAVE_STRNDUP || defined strndup
#define _zzip_strndup strndup
#else
/* if your system does not have strndup: */
zzip__new__ static char *
_zzip_strndup(char const *p, size_t maxlen)
{
if (p == NULL)
{
return p;
} else
{
size_t len = strnlen(p, maxlen);
char* r = malloc(len + 1);
if (r == NULL)
return NULL; /* errno = ENOMEM */
r[len] = '\0';
return memcpy(r, p, len);
}
}
#endif
#if defined ZZIP_HAVE_STRCASECMP || defined strcasecmp
#define _zzip_strcasecmp strcasecmp
#else
/* if your system does not have strcasecmp: */
static int
_zzip_strcasecmp(char *__zzip_restrict a, char *_zzip_restrict b)
{
if (! a)
return (b) ? 1 : 0;
if (! b)
return -1;
while (1)
{
int v = tolower(*a) - tolower(*b);
if (v)
return v;
if (! *a)
return 1;
if (! *b)
return -1;
a++;
b++;
}
}
#endif
#endif

5
tests/gating/build/test.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
(gcc unzzip.c unzzipcat-zip.c unzzipdir-mix.c -lzzip -o foo && ./foo) || exit 1
rm ./foo
exit 0

View File

@ -0,0 +1,24 @@
#ifndef UNZZIP_STATES_H
#define UNZZIP_STATES_H
/* DIAGNOSTICS according to the unzip(1) manpage */
#define EXIT_OK 0
#define EXIT_WARNINGS 1
#define EXIT_ERRORS 2
#define EXIT_FILEFORMAT 3
#define EXIT_ENOMEM 4
#define EXIT_ENOTTY_FOR_PASSWORD 5
#define EXIT_ENOMEM_ZIP_TO_DISK 6
#define EXIT_ENOMEM_ZIP_TO_MEM 7
#define EXIT_ZIP_NOT_FOUND 9
#define EXIT_INVALID_OPTION 10
#define EXIT_FILE_NOT_FOUND 11
#define EXIT_DISKFULL 50
#define EXIT_EARLY_END_OF_FILE 51
#define EXIT_SIGTERM 80
#define EXIT_UNSUPPORTED_COMPRESSION 81
#define EXIT_WRONG_PASSWORD 82
#endif

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
* Use freely under the restrictions of the ZLIB license.
*
* This file is used as an example to clarify zzip api usage.
*/
#include <zzip/zzip.h>
#include <stdio.h>
#include <string.h>
#include "unzzipcat-zip.h"
#include "unzzipdir-zip.h"
#include "unzzip-states.h"
static const char usage[] =
{
"unzzip <dir>.. \n"
" - unzzip the files contained in a zip archive.\n"
" -p print content of files to pipe\n"
" -l list names in archive (short format)\n"
};
static int unzzip_version(void)
{
printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
return 0;
}
static int unzzip_help(void)
{
printf (usage);
return 0;
}
int
main (int argc, char ** argv)
{
int argn;
int exitcode = 0;
zzip_error_t error;
if (argc <= 1 || ! strcmp (argv[1], "--help"))
{
return unzzip_help();
}
if (! strcmp (argv[1], "--version"))
{
return unzzip_version();
}
if (! strcmp (argv[1], "-l") || ! strcmp(argv[1], "--list"))
{
argc -= 1; argv += 1;
return unzzip_show_list(argc, argv);
}
if (! strcmp (argv[1], "-v") || ! strcmp(argv[1], "--versions"))
{
if (argc == 2)
return unzzip_version(); /* compatible with info-zip */
argc -= 1; argv += 1;
return unzzip_long_list(argc, argv);
}
if (! strcmp (argv[1], "-p") || ! strcmp(argv[1], "--pipe"))
{
argc -= 1; argv += 1;
return unzzip_print(argc, argv);
}
if (! strcmp (argv[1], "-"))
{
fprintf(stderr, "unknown option %s", argv[1]);
return EXIT_INVALID_OPTION;
}
return unzzip_extract(argc, argv);
}
/*
* Local variables:
* c-file-style: "stroustrup"
* End:
*/

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
* Use freely under the restrictions of the ZLIB license.
*
* This file is used as an example to clarify zzip api usage.
*/
#include <zzip/lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "__mkdir.h"
#include "__string.h"
#include "__fnmatch.h"
#include "__debug.h"
#include "unzzipcat-zip.h"
#include "unzzip-states.h"
#ifdef ZZIP_HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef ZZIP_HAVE_IO_H
#include <io.h>
#endif
static int exitcode(int e)
{
switch (e)
{
case ZZIP_NO_ERROR:
return EXIT_OK;
case ZZIP_OUTOFMEM: /* out of memory */
return EXIT_ENOMEM;
case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */
return EXIT_ZIP_NOT_FOUND;
case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */
case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */
case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */
case ZZIP_DIR_TOO_SHORT:
case ZZIP_DIR_EDH_MISSING:
return EXIT_FILEFORMAT;
case ZZIP_DIRSIZE:
return EXIT_EARLY_END_OF_FILE;
case ZZIP_ENOENT:
return EXIT_FILE_NOT_FOUND;
case ZZIP_UNSUPP_COMPR:
return EXIT_UNSUPPORTED_COMPRESSION;
case ZZIP_CORRUPTED:
case ZZIP_UNDEF:
case ZZIP_DIR_LARGEFILE:
return EXIT_FILEFORMAT;
}
return EXIT_ERRORS;
}
static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out)
{
ZZIP_FILE* file = zzip_file_open (disk, name, 0);
if (file)
{
char buffer[1024]; int len;
while ((len = zzip_file_read (file, buffer, 1024)))
{
fwrite (buffer, 1, len, out);
}
zzip_file_close (file);
}
}
/*
* 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, '/');
if (p) {
char* dir_name = _zzip_strndup(name, p-name);
makedirs(dir_name);
free (dir_name);
}
if (_zzip_mkdir(name, 0775) == -1 && errno != EEXIST)
{
DBG3("while mkdir %s : %s", name, strerror(errno));
}
errno = 0;
}
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, '/');
if (p) {
char* dir_name = _zzip_strndup(name, p-name);
makedirs(dir_name);
free (dir_name);
}
}
fp = fopen(name, mode);
if (mustfree)
free(name_stripped);
return fp;
}
static int unzzip_cat (int argc, char ** argv, int extract)
{
int done = 0;
int argn;
ZZIP_DIR* disk;
zzip_error_t error;
if (argc == 1)
{
printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
return EXIT_OK; /* better provide an archive argument */
}
disk = zzip_dir_open (argv[1], &error);
if (! disk) {
fprintf(stderr, "%s: %s\n", argv[1], zzip_strerror(error));
return exitcode(error);
}
if (argc == 2)
{ /* list all */
ZZIP_DIRENT entry;
while(zzip_dir_read(disk, &entry))
{
char* name = entry.d_name;
FILE* out = stdout;
if (extract) out = create_fopen(name, "w", 1);
if (! out) {
DBG3("fopen' %s : %s", name, strerror(errno));
if (errno != EISDIR) done = EXIT_ERRORS;
continue;
}
unzzip_cat_file (disk, name, out);
if (extract) fclose(out);
}
}
else
{ /* list only the matching entries - in order of zip directory */
ZZIP_DIRENT entry;
while(zzip_dir_read(disk, &entry))
{
char* name = entry.d_name;
for (argn=1; argn < argc; argn++)
{
if (! _zzip_fnmatch (argv[argn], name,
FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
{
FILE* out = stdout;
if (extract) out = create_fopen(name, "w", 1);
if (! out) {
DBG3("fopen. %s : %s", name, strerror(errno));
if (errno != EISDIR) done = EXIT_ERRORS;
continue;
}
unzzip_cat_file (disk, name, out);
if (extract) fclose(out);
break; /* match loop */
}
}
}
}
zzip_dir_close(disk);
return done;
}
int unzzip_print (int argc, char ** argv)
{
return unzzip_cat(argc, argv, 0);
}
int unzzip_extract (int argc, char ** argv)
{
return unzzip_cat(argc, argv, 1);
}
/*
* Local variables:
* c-file-style: "stroustrup"
* End:
*/

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
* Use freely under the restrictions of the ZLIB license.
*
* This file is used as an example to clarify zzip api usage.
*/
extern int unzzip_print(int argc, char** argv);
extern int unzzip_extract(int argc, char** argv);

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
* Use freely under the restrictions of the ZLIB license.
*
* This file is used as an example to clarify zzip api usage.
*/
#include <zzip/lib.h>
#include "__debug.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unzzipdir-zip.h"
#include "unzzip-states.h"
#ifdef ZZIP_HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef ZZIP_HAVE_IO_H
#include <io.h>
#endif
#ifdef ZZIP_HAVE_FNMATCH_H
#include <fnmatch.h>
#else
#define fnmatch(x,y,z) strcmp(x,y)
#endif
static const char* comprlevel[] = {
"stored", "shrunk", "redu:1", "redu:2", "redu:3", "redu:4",
"impl:N", "toknze", "defl:N", "defl:B", "impl:B" };
static int exitcode(int e)
{
switch (e)
{
case ZZIP_NO_ERROR:
return EXIT_OK;
case ZZIP_OUTOFMEM: /* out of memory */
return EXIT_ENOMEM;
case ZZIP_DIR_OPEN: /* failed to open zipfile, see errno for details */
return EXIT_ZIP_NOT_FOUND;
case ZZIP_DIR_STAT: /* failed to fstat zipfile, see errno for details */
case ZZIP_DIR_SEEK: /* failed to lseek zipfile, see errno for details */
case ZZIP_DIR_READ: /* failed to read zipfile, see errno for details */
case ZZIP_DIR_TOO_SHORT:
case ZZIP_DIR_EDH_MISSING:
return EXIT_FILEFORMAT;
case ZZIP_DIRSIZE:
return EXIT_EARLY_END_OF_FILE;
case ZZIP_ENOENT:
return EXIT_FILE_NOT_FOUND;
case ZZIP_UNSUPP_COMPR:
return EXIT_UNSUPPORTED_COMPRESSION;
case ZZIP_CORRUPTED:
case ZZIP_UNDEF:
case ZZIP_DIR_LARGEFILE:
return EXIT_FILEFORMAT;
}
return EXIT_ERRORS;
}
static int
unzzip_list (int argc, char ** argv, int verbose)
{
int argn;
ZZIP_DIR* disk;
if (argc == 1)
{
printf (__FILE__" version "ZZIP_PACKAGE" "ZZIP_VERSION"\n");
return EXIT_OK; /* better provide an archive argument */
}
disk = zzip_opendir (argv[1]);
if (! disk) {
DBG3("opendir failed [%i] %s", errno, strerror(errno));
perror(argv[1]);
return exitcode(errno);
}
if (argc == 2)
{ /* list all */
ZZIP_DIRENT* entry = 0;
while((entry = zzip_readdir(disk)))
{
char* name = entry->d_name;
long long usize = entry->st_size;
if (!verbose)
{
printf ("%22lli %s\n", usize, name);
} else
{
long long csize = entry->d_csize;
unsigned compr = entry->d_compr;
const char* defl = (compr < sizeof(comprlevel)) ? comprlevel[compr] : "(redu)";
printf ("%lli/%lli %s %s\n", usize, csize, defl, name);
}
}
DBG2("readdir done %s", strerror(errno));
}
else
{ /* list only the matching entries - in order of zip directory */
ZZIP_DIRENT* entry = 0;
while((entry = zzip_readdir(disk)))
{
char* name = entry->d_name;
for (argn=1; argn < argc; argn++)
{
if (! fnmatch (argv[argn], name,
FNM_NOESCAPE|FNM_PATHNAME|FNM_PERIOD))
{
long long usize = entry->st_size;
if (!verbose)
{
printf ("%22lli %s\n", usize, name);
} else
{
long long csize = entry->d_csize;
unsigned compr = entry->d_compr;
const char* defl = (compr < sizeof(comprlevel)) ? comprlevel[compr] : "(redu)";
printf ("%lli/%lli %s %s\n", usize, csize, defl, name);
}
break; /* match loop */
}
}
}
DBG2("readdir done %s", strerror(errno));
}
zzip_closedir(disk);
return 0;
}
int
unzzip_long_list (int argc, char ** argv)
{
return unzzip_list(argc, argv, 1);
}
int
unzzip_show_list (int argc, char ** argv)
{
return unzzip_list(argc, argv, 0);
}
/*
* Local variables:
* c-file-style: "stroustrup"
* End:
*/

View File

@ -0,0 +1,10 @@
/*
* Copyright (c) 2003 Guido Draheim <guidod@gmx.de>
* Use freely under the restrictions of the ZLIB license.
*
* This file is used as an example to clarify zzip api usage.
*/
extern int unzzip_show_list(int argc, char** argv);
extern int unzzip_long_list(int argc, char** argv);

21
tests/tests.yml Normal file
View File

@ -0,0 +1,21 @@
---
- hosts: localhost
vars:
- artifacts: ./artifacts
remote_user: root
roles:
- role: standard-test-basic
tags:
- atomic
- classic
- container
tests:
- simple:
dir: gating
run: ./all.sh
required_packages:
- zziplib
- zziplib-devel
- zziplib-utils
- coreutils
- gcc

View File

@ -1,35 +1,29 @@
Summary: Lightweight library to easily extract data from zip files
Name: zziplib
Version: 0.13.68
Release: 9%{?dist}
Version: 0.13.71
Release: 10%{?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
#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
#Using the pruned version of the upstream archive. The archive does not contain the Source1 and Source2 files. Their github version is used instead (the original ones had licensing issues)
#rhbz#1982241
Source0: v%{version}-pruned.tar.gz
#https://raw.githubusercontent.com/gdraheim/zziplib/465450c86c930026664329876e5350d21a7527db/docs/zzipdoc/match.py
Source1: match.py
#https://raw.githubusercontent.com/gdraheim/zziplib/465450c86c930026664329876e5350d21a7527db/docs/zzipdoc/options.py
Source2: options.py
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
Patch1: CVE-2020-18442.patch
Patch2: CVE-2020-18770.patch
Patch100: multilib-32.patch
Patch101: multilib-64.patch
BuildRequires: make
BuildRequires: gcc
BuildRequires: perl-interpreter
BuildRequires: python3-devel
BuildRequires: python3-six
BuildRequires: python3
BuildRequires: python3-rpm-macros
BuildRequires: zip
BuildRequires: xmlto
BuildRequires: zlib-devel
@ -47,7 +41,6 @@ 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
@ -61,7 +54,6 @@ 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
@ -79,52 +71,41 @@ zziplib library.
%prep
%setup -q
cp %{SOURCE1} docs/zzipdoc/
cp %{SOURCE2} docs/zzipdoc/
%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
--enable-frame-pointer
# 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
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
pushd %{_builddir}/zziplib-%{version}
%ifarch i686 armv7hl
%apply_patch %{PATCH101} -p2
patch -p2 < %{PATCH100}
%endif
%ifnarch i686 armv7hl
%apply_patch %{PATCH100} -p2
patch -p2 < %{PATCH101}
%endif
cd ..
popd
%{__make} %{?_smp_mflags}
%make_build
%install
make install DESTDIR=%{buildroot}
%make_install
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%ldconfig_scriptlets
%files
%doc docs/COPYING* ChangeLog README TODO
@ -134,7 +115,7 @@ make install DESTDIR=%{buildroot}
%{_bindir}/*
%files devel
%doc docs/README.SDL docs/*.htm docs/*.html
%doc docs/README.SDL docs/*.htm
%{_includedir}/*
%exclude %{_libdir}/*.la
%{_libdir}/*.so
@ -143,39 +124,89 @@ make install DESTDIR=%{buildroot}
%{_mandir}/man3/*
%changelog
* Mon Aug 02 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.68-9
* Wed Jan 24 2024 Jakub Martisko <jamartis@redhat.com> - 0.13.71-10
- Fix CVE-2020-18770
Resolves: RHEL-14967
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 0.13.71-9
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Tue Jul 27 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-8
- Add gating tests
Resolves: rhbz#1986332
* Fri Jul 23 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-7
- Remove the doc/zzipdoc/{options,match}.py scritps from the original tar
- Replace them with a current github version
- The original version of the files contains autogenerated header with incompatible license
- This build thus uses modified tar archive
Resolves: rhbz#1982241
* Thu Jul 22 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-6
- Fix CVE-2020-18442
- Resolves: CVE-2020-18442
Resolves: CVE-2020-18442
Resolves: 1977964
* Tue Oct 16 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-8
- Fix CVE-2018-17828 in the "single z" binaries
- Resolves: #1772447
* Thu Jul 22 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-5
- Refresh the multilib patch
Resolves: rhbz#1915747
* Tue Oct 16 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-7
- Fix CVE-2018-17828
- Resolves: #1635890
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.13.71-4
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Thu Oct 11 2018 Jakub Martisko <jamartis@redhat.com> - 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
* Mon Feb 01 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-3
- Use python3 (versioned) as buildrequires
* Thu Oct 04 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-5
- Fix memory leak caused by the CVE-2018-16548
- Resolves: #1626202
* Thu Jan 28 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.71-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Mon Aug 13 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-4
- Change the build dependency to python-devel and use the pathfix.py script
- Related: 1592262
* Thu Jan 21 2021 Jakub Martisko <jamartis@redhat.com> - 0.13.71-1
- Rebase to 0.13.71
- Drop the CVE patches, they are now part of the upstream package
- Build no longer requires python2
- Resolves: 1807565
* Sat Jul 28 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-3
- Fix CVEs 2018-7725, 2018-7726, 2018-7727, 2018-6484, 2018-6869
- Resolves: 1555082
- Resolves: 1545818
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.69-9
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Tue Jul 03 2018 Jakub Martisko <jamartis@redhat.com> - 0.13.68-2
- Port documentation generating scripts to Python 3
- Include both docs/*.htm and docs/*html files
* Tue Jul 14 2020 Tom Stellard <tstellar@redhat.com> - 0.13.69-8
- Use make macros
- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro
* Fri Jan 31 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.69-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Sat Jul 27 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.69-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Sun Feb 03 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.69-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Thu Jan 24 2019 Jakub Martisko <jamartis@redhat.com> - 0.13.69-4
- Add the missing CVE-2018-17828.part2.patch file
- Fix Formating of the previous 2 changelog entries
* Thu Jan 24 2019 Jakub Martisko <jamartis@redhat.com> - 0.13.69-3
- Related: #1626202
- Resolves: CVE-2018-16548
* Thu Jan 24 2019 Jakub Martisko <jamartis@redhat.com> - 0.13.69-2
- Related: 1635890
- Resolves: CVE-2018-17828
* Mon Jul 23 2018 Alexander Bokovoy <abokovoy@redhat.com> - 0.13.69-1
- Update to 0.13.69 release
- Fixes: #1598246 (CVE-2018-6541)
- Fixes: #1554673 (CVE-2018-7727)
- Use versioned python executables everywhere
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.68-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Sun Mar 18 2018 Iryna Shcherbina <ishcherb@redhat.com> - 0.13.68-2
- Update Python 2 dependency declarations to new packaging standards
(See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3)
* Wed Feb 14 2018 Alexander Bokovoy <abokovoy@redhat.com> - 0.13.68-1
- 0.13.68