Ethereal-dev: [Ethereal-dev] [Patch] Prevent crash if -r argument is a FIFO

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Graeme Hewson <ghewson@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 05 Jun 2002 22:02:36 +0100
Presently, if the argument to -r is a FIFO, ethereal and tetheral
crash.  It musn't be a FIFO because (t)ethereal wants to seek on it; the
attached patch to wiretap/file.c prevents the user specifying a FIFO.

It turns out there's a more fundamental reason for the crash, though. 
There's a bug in zlib 1.1.3 and 1.1.4 (and presumably earlier versions
too) where gzseek() doesn't save its internal error status if its call
to fseek() fails. This means a subsequent call to gzerror() sets errnum
to whatever the error was before the call to gzseek(), which is likely
to be Z_OK (gzopen() and gzdopen() initialise the error status to
Z_OK).  The open_cap_file() routines in file.c and tethereal.c get
fooled and pass back an error status of 0 to their callers if
wtap_open_offline() fails in its call to file_seek().  Attached are
patches to these two files.  The patch to file_wrappers.c merely
documents the problem.

I reported the problem to the zlib developers yesterday, but I haven't
heard back from them yet.

No doubt there could be more complicated workarounds, but as far as I
can see with a quick look, there are no other places where Ethereal gets
caught badly by the zlib problem -- the worst that could happen is that
the user receives an error message saying "error: success".  How likely
is an error in fseek() with a regular file anyway?  The open_cap_file()
patches have the advantage that the functions don't need to be changed
when zlib gets fixed.


Graeme Hewson
--- file.c.orig	Thu May 23 11:27:12 2002
+++ file.c	Wed Jun  5 19:07:17 2002
@@ -198,7 +198,13 @@
 fail:
   simple_dialog(ESD_TYPE_CRIT, NULL,
 			file_open_error_message(err, FALSE), fname);
-  return (err);
+/*
+ * Due to a bug in zlib (1.1.4 is the current release as of 5 June 2002;
+ * 1.1.5 is not yet available), err can be 0 if the call to file_seek in
+ * wtap_open_offline() failed.  Routines which call us only care if the
+ * return value is zero or non-zero, so return 1 on failure instead of err.
+ */
+  return (1);
 }
 
 /* Reset everything to a pristine state */
--- file_wrappers.c.orig	Wed Feb  6 09:58:30 2002
+++ file_wrappers.c	Wed Jun  5 19:55:51 2002
@@ -131,6 +131,18 @@
 	switch (errnum) {
 
 	case Z_OK:		/* no error */
+/*
+ * There's a bug in zlib 1.1.4 (and presumably earlier versions too)
+ * where gzseek() doesn't save its internal error status if its call
+ * to fseek() fails. This means the subsequent call to gzerror() sets
+ * errnum to whatever the error was before the call to gzseek(), which
+ * is likely to be Z_OK. We don't work around the bug here, but leave
+ * it to the caller not to be fooled by file_error() returning 0 after
+ * a failed call to file_seek().
+ *
+ * There's a similar bug in gzrewind(), but as of Ethereal 0.9.4 there
+ * are no calls to this function.
+ */
 		return 0;
 
 	case Z_STREAM_END:	/* EOF - not an error */
--- tethereal.c.orig	Thu May 23 00:22:55 2002
+++ tethereal.c	Wed Jun  5 19:08:22 2002
@@ -1818,5 +1818,11 @@
 fail:
   snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
   fprintf(stderr, "tethereal: %s\n", err_msg);
-  return (err);
+/*
+ * Due to a bug in zlib (1.1.4 is the current release as of 5 June 2002;
+ * 1.1.5 is not yet available), err can be 0 if the call to file_seek in
+ * wtap_open_offline() failed.  Our caller only cares if the return value
+ * is zero or non-zero, so return 1 on failure instead of err.
+ */
+  return (1);
 }
--- wiretap/file.c.orig	Wed May 29 03:19:49 2002
+++ wiretap/file.c	Wed Jun  5 19:14:14 2002
@@ -181,7 +181,7 @@
 		*err = errno;
 		return NULL;
 	}
-	if (! S_ISREG(statb.st_mode) && ! S_ISFIFO(statb.st_mode)) {
+	if (! S_ISREG(statb.st_mode)) {
 		if (S_ISDIR(statb.st_mode))
 			*err = EISDIR;
 		else