Multiple vendors ZOO file decompression infinite loop DoS
http://archives.neohapsis.com/archives/bugtraq/2007-05/0046.html

It's possible to make the ZOO implementation to enter in an infinite loop
condition. The vulnerability lies in the algorithm used to locate the
files inside the archive. Each file in a ZOO archive is identified by a
direntry structure. Those structures are linked between themselves with a
'next' pointer. This pointer is in fact an offset from the beginning of
the file, representing the next direntry structure. By specifying an
already processed file, it's possible to process more than one time this
same file. The ZOO parser will then enter an infinite loop condition. 
Index: zoo-2.10/zooext.c
===================================================================
--- zoo-2.10.orig/zooext.c	2008-03-22 16:49:23.000000000 -0300
+++ zoo-2.10/zooext.c	2008-03-22 16:51:30.000000000 -0300
@@ -90,6 +90,7 @@
 #endif
 struct direntry direntry;                 /* directory entry */
 int first_dir = 1;								/* first dir entry seen? */
+unsigned long zoo_pointer = 0;            /* Track our position in the file */
 
 static char extract_ver[] = "Zoo %d.%d is needed to extract %s.\n";
 static char no_space[] = "Insufficient disk space to extract %s.\n";
@@ -174,6 +175,9 @@
 		exit_status = 1;
    }
    zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data begins */
+
+   /* Begin tracking our position in the file */
+   zoo_pointer = zoo_header.zoo_start;
 }
 
 #ifndef PORTABLE
@@ -602,6 +606,11 @@
    } /* end if */
 
 loop_again:
+   /* Make sure we are not seeking to already processed data */
+   if (next_ptr <= zoo_pointer)
+     prterror ('f', "ZOO chain structure is corrupted\n");
+   zoo_pointer = next_ptr;
+
    zooseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
 } /* end while */
 
Index: zoo-2.10/zoolist.c
===================================================================
--- zoo-2.10.orig/zoolist.c	2008-03-22 16:49:30.000000000 -0300
+++ zoo-2.10/zoolist.c	2008-03-22 16:50:44.000000000 -0300
@@ -93,6 +93,7 @@
 int show_mode = 0;				/* show file protection */
 #endif
 int first_dir = 1;				/* if first direntry -- to adjust dat_ofs */
+unsigned long zoo_pointer = 0; /* Track our position in the file */
 
 while (*option) {
    switch (*option) {
@@ -212,6 +213,9 @@
 		show_acmt (&zoo_header, zoo_file, 0);		/* show archive comment */
 	}
 
+   /* Begin tracking our position in the file */
+   zoo_pointer = zoo_header.zoo_start;
+
    /* Seek to the beginning of the first directory entry */
    if (zooseek (zoo_file, zoo_header.zoo_start, 0) != 0) {
       ercount++;
@@ -438,6 +442,11 @@
          if (verb_list && !fast)
             show_comment (&direntry, zoo_file, 0, (char *) NULL);
       } /* end if (lots of conditions) */
+
+      /* Make sure we are not seeking to already processed data */
+      if (direntry.next <= zoo_pointer)
+        prterror ('f', "ZOO chain structure is corrupted\n");
+      zoo_pointer = direntry.next;
    
 		/* ..seek to next dir entry */
       zooseek (zoo_file, direntry.next, 0);
