On 16:07 Fri 17 Jul     , Fathi Boudra (Debian) wrote:
FBD> Hi,

>> I have uploaded new package (goldendict) which depends to libzip.
>> It uses dictionaries which represent as archives. Some of them have
>> more than 64K entries. Current version of libzip/Debian doesn't
>> support such archives.
>> 
>> Upstream has already contained fix for this issue
>> http://hg.nih.at/libzip/, so I set tags fixed-upstream and patch.
>> 
>> Could You make a backport these patches to solve the problem, or
>> make the package with last snapshot from upstream ?
FBD> I tried to apply the relevant changesets (778 and 780) but it isn't enough.
FBD> I would prefer to upload an official release instead of a snapshot.
FBD> Libzip 0.9 was released a year ago, it could be nice to have an new 
upstream release.
FBD> I cc'ed authors to the bug report reply, maybe they have planned it soon.

FBD> cheers,

FBD> Fathi

Hi! I wrote to upstream and as a result they sent me the patch for
version 0.9. It can be found in attache.

--
... mpd paused: Manowar - Call To Arms

. ''`.                               Dmitry E. Oboukhov
: :’  :   email: [email protected] jabber://[email protected]
`. `~’              GPGKey: 1024D / F8E26537 2006-11-21
  `- 1B23 D4F8 8EC0 D902 0555  E438 AB8C 00CF F8E2 6537
diff -ru libzip-0.9/lib/zip_close.c libzip-0.9-64k/lib/zip_close.c
--- libzip-0.9/lib/zip_close.c	2008-07-02 14:58:09.000000000 +0200
+++ libzip-0.9-64k/lib/zip_close.c	2009-07-28 20:41:08.000000000 +0200
@@ -191,7 +191,8 @@
 		error = 1;
 		break;
 	    }
-	    if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) {
+	    if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1,
+				 &za->error) != 0) {
 		error = 1;
 		break;
 	    }
diff -ru libzip-0.9/lib/zip_dirent.c libzip-0.9-64k/lib/zip_dirent.c
--- libzip-0.9/lib/zip_dirent.c	2008-07-02 14:58:09.000000000 +0200
+++ libzip-0.9-64k/lib/zip_dirent.c	2009-07-28 20:45:30.000000000 +0200
@@ -68,6 +68,30 @@
 
 
 
+int
+_zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
+{
+    struct zip_dirent *entry;
+
+    if (nentry < cd->nentry) {
+	_zip_error_set(error, ZIP_ER_INTERNAL, 0);
+	return -1;
+    }
+
+    if ((entry=((struct zip_dirent *)
+		realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) {
+	_zip_error_set(error, ZIP_ER_MEMORY, 0);
+	return -1;
+    }
+
+    cd->nentry = nentry;
+    cd->entry = entry;
+
+    return 0;
+}
+
+
+
 struct zip_cdir *
 _zip_cdir_new(int nentry, struct zip_error *error)
 {
@@ -173,19 +197,23 @@
    Fills the zip directory entry zde.
 
    If bufp is non-NULL, data is taken from there and bufp is advanced
-   by the amount of data used; no more than left bytes are used.
-   Otherwise data is read from fp as needed.
+   by the amount of data used; otherwise data is read from fp as needed.
+   
+   if leftp is non-NULL, no more bytes than specified by it are used,
+   and *leftp is reduced by the number of bytes used.
 
-   If localp != 0, it reads a local header instead of a central
+   If local != 0, it reads a local header instead of a central
    directory entry.
 
    Returns 0 if successful. On error, error is filled in and -1 is
    returned.
+
+   XXX: leftp and file position undefined on error.
 */
 
 int
 _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
-		 unsigned char **bufp, unsigned int left, int localp,
+		 unsigned char **bufp, unsigned int *leftp, int local,
 		 struct zip_error *error)
 {
     unsigned char buf[CDENTRYSIZE];
@@ -193,18 +221,19 @@
     unsigned short dostime, dosdate;
     unsigned int size;
 
-    if (localp)
+    if (local)
 	size = LENTRYSIZE;
     else
 	size = CDENTRYSIZE;
-    
+
+    if (leftp && (*leftp < size)) {
+	_zip_error_set(error, ZIP_ER_NOZIP, 0);
+	return -1;
+    }
+
     if (bufp) {
 	/* use data from buffer */
 	cur = *bufp;
-	if (left < size) {
-	    _zip_error_set(error, ZIP_ER_NOZIP, 0);
-	    return -1;
-	}
     }
     else {
 	/* read entry from disk */
@@ -212,11 +241,10 @@
 	    _zip_error_set(error, ZIP_ER_READ, errno);
 	    return -1;
 	}
-	left = size;
 	cur = buf;
     }
 
-    if (memcmp(cur, (localp ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
+    if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
 	_zip_error_set(error, ZIP_ER_NOZIP, 0);
 	return -1;
     }
@@ -225,7 +253,7 @@
     
     /* convert buffercontents to zip_dirent */
     
-    if (!localp)
+    if (!local)
 	zde->version_madeby = _zip_read2(&cur);
     else
 	zde->version_madeby = 0;
@@ -245,7 +273,7 @@
     zde->filename_len = _zip_read2(&cur);
     zde->extrafield_len = _zip_read2(&cur);
     
-    if (localp) {
+    if (local) {
 	zde->comment_len = 0;
 	zde->disk_number = 0;
 	zde->int_attrib = 0;
@@ -263,13 +291,14 @@
     zde->extrafield = NULL;
     zde->comment = NULL;
 
-    if (bufp) {
-	if (left < CDENTRYSIZE + (zde->filename_len+zde->extrafield_len
-				  +zde->comment_len)) {
-	    _zip_error_set(error, ZIP_ER_NOZIP, 0);
-	    return -1;
-	}
+    size += zde->filename_len+zde->extrafield_len+zde->comment_len;
+
+    if (leftp && (*leftp < size)) {
+	_zip_error_set(error, ZIP_ER_NOZIP, 0);
+	return -1;
+    }
 
+    if (bufp) {
 	if (zde->filename_len) {
 	    zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error);
 	    if (!zde->filename)
@@ -312,6 +341,8 @@
 
     if (bufp)
       *bufp = cur;
+    if (leftp)
+	*leftp -= size;
 
     return 0;
 }
diff -ru libzip-0.9/lib/zip_file_get_offset.c libzip-0.9-64k/lib/zip_file_get_offset.c
--- libzip-0.9/lib/zip_file_get_offset.c	2007-11-07 14:33:45.000000000 +0100
+++ libzip-0.9-64k/lib/zip_file_get_offset.c	2009-07-28 20:41:28.000000000 +0200
@@ -63,7 +63,7 @@
 	return 0;
     }
 
-    if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0)
+    if (_zip_dirent_read(&de, za->zp, NULL, NULL, 1, &za->error) != 0)
 	return 0;
 
     offset += LENTRYSIZE + de.filename_len + de.extrafield_len;
diff -ru libzip-0.9/lib/zip_open.c libzip-0.9-64k/lib/zip_open.c
--- libzip-0.9/lib/zip_open.c	2008-07-24 12:36:48.000000000 +0200
+++ libzip-0.9-64k/lib/zip_open.c	2009-07-28 20:46:30.000000000 +0200
@@ -154,6 +154,7 @@
     struct zip_cdir *cd;
     unsigned char *cdp, **bufp;
     int i, comlen, nentry;
+    unsigned int left;
 
     comlen = buf + buflen - eocd - EOCDLEN;
     if (comlen < 0) {
@@ -207,7 +208,6 @@
 	}
     }
 
-    cdp = eocd;
     if (cd->size < (unsigned int)(eocd-buf)) {
 	/* if buffer already read in, use it */
 	cdp = eocd - cd->size;
@@ -231,14 +231,23 @@
 	}
     }
 
-    for (i=0; i<cd->nentry; i++) {
-	if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0,
-			      error)) < 0) {
+    left = cd->size;
+    i=0;
+    do {
+	if (i == cd->nentry && left > 0) {
+	    /* Infozip extension for more than 64k entries:
+	       nentries wraps around, size indicates correct EOCD */
+	    _zip_cdir_grow(cd, cd->nentry+0x10000, error);
+	}
+
+	if ((_zip_dirent_read(cd->entry+i, fp, bufp, &left, 0, error)) < 0) {
 	    cd->nentry = i;
 	    _zip_cdir_free(cd);
 	    return NULL;
 	}
-    }
+	i++;
+	
+    } while (i<cd->nentry);
     
     return cd;
 }
@@ -287,7 +296,7 @@
 	    return -1;
 	}
 	
-	if (_zip_dirent_read(&temp, fp, NULL, 0, 1, error) == -1)
+	if (_zip_dirent_read(&temp, fp, NULL, NULL, 1, error) == -1)
 	    return -1;
 	
 	if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) {
diff -ru libzip-0.9/lib/zipint.h libzip-0.9-64k/lib/zipint.h
--- libzip-0.9/lib/zipint.h	2008-07-21 17:14:34.000000000 +0200
+++ libzip-0.9-64k/lib/zipint.h	2009-07-28 20:45:05.000000000 +0200
@@ -217,13 +217,14 @@
 
 int _zip_cdir_compute_crc(struct zip *, uLong *);
 void _zip_cdir_free(struct zip_cdir *);
+int _zip_cdir_grow(struct zip_cdir *, int, struct zip_error *);
 struct zip_cdir *_zip_cdir_new(int, struct zip_error *);
 int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *);
 
 void _zip_dirent_finalize(struct zip_dirent *);
 void _zip_dirent_init(struct zip_dirent *);
-int _zip_dirent_read(struct zip_dirent *, FILE *,
-		     unsigned char **, unsigned int, int, struct zip_error *);
+int _zip_dirent_read(struct zip_dirent *, FILE *, unsigned char **,
+		     unsigned int *, int, struct zip_error *);
 void _zip_dirent_torrent_normalize(struct zip_dirent *);
 int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *);
 

Attachment: signature.asc
Description: Digital signature

Reply via email to