Ethereal-dev: [Ethereal-dev] Problem printing broken TFTP packets

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

From: Santeri Paavolainen <santtu@xxxxxxx>
Date: Tue, 9 Apr 2002 09:58:07 +0300 (EEST)
Hello,

I stumbled on a problem when printing broken TFTP packets (they were not
terminated correctly) and printing. The basic problem is that File/Print
or File/Print packet allow raw data from the packet to be printed without
checking whether the characters actually are printable.

Thus when printing the attached packet some data from the packet is
printed verbatim (both plain text and postscript mode), which causes the
given print data to contain control codes, which then the printer will
interpret ... and print garbage.

I made a quick patch which adds text_clean_string and modifies
ps_clean_string to change characters in range 000 to 037 into ^@ to ^Z
(two characters, "^" + "[@-Z]"). This fixes the problem at least on the HP
LaserJet I tested. Have a look over the patch, as its a quick one.

BTW the original ps_clean_string suffers seriously from a case of
unterminated string buffer: whenever the 'in' is longer than 'out' the
'out' will not be NUL-terminated.

-- 
santtu@xxxxxx                    I have become death, destroyer of the worlds.

Attachment: tftp-invalid.pcap
Description: Binary data

--- ethereal-0.9.3-orig/print.c	Fri Mar 15 04:44:49 2002
+++ ethereal-0.9.3/print.c	Tue Apr  9 09:56:39 2002
@@ -41,7 +41,11 @@
 #include "util.h"
 #include <epan/tvbuff.h>
 
+#define MAX_LINE_LENGTH 256
+
 static void proto_tree_print_node_text(GNode *node, gpointer data);
+static void text_clean_string(unsigned char *out, const unsigned char *in,
+			int outbuf_size);
 static void proto_tree_print_node_ps(GNode *node, gpointer data);
 static void ps_clean_string(unsigned char *out, const unsigned char *in,
 			int outbuf_size);
@@ -159,6 +163,7 @@
 	const guint8	*pd;
 	gchar		label_str[ITEM_LABEL_LENGTH];
 	gchar		*label_ptr;
+	char		textbuffer[MAX_LINE_LENGTH]; /* static sized buffer! */
 
 	/* Don't print invisible entries. */
 	if (!fi->visible)
@@ -185,7 +190,8 @@
 	space[num_spaces] = '\0';
 
 	/* Print the text */
-	fprintf(pdata->fh, "%s%s\n", space, label_ptr);
+        	text_clean_string(textbuffer, label_ptr, MAX_LINE_LENGTH);
+	fprintf(pdata->fh, "%s%s\n", space, textbuffer);
 
 	/* If it's uninterpreted data, dump it (unless our caller will
 	   be printing the entire packet in hex). */
@@ -209,6 +215,26 @@
 	}
 }
 
+static
+void text_clean_string(unsigned char *out, const unsigned char *in,
+			int outbuf_size)
+{
+        while (outbuf_size > 1 && *in) {
+                if (*in >= '\000' && *in <= '\037') {
+                        *out++ = '^';
+                        outbuf_size--;
+                        if (outbuf_size > 1)
+                                *out++ = *in++ + '@';
+                } else {
+                        *out++ = *in++;
+                }
+
+                outbuf_size--;
+        }
+
+        *out = '\0';
+}
+
 void print_hex_data(FILE *fh, gint format, frame_data *fd)
 {
 	gboolean multiple_sources;
@@ -288,8 +314,6 @@
 
 }
 
-#define MAX_LINE_LENGTH 256
-
 /* Print a node's data, and any child nodes, in PostScript */
 static
 void proto_tree_print_node_ps(GNode *node, gpointer data)
@@ -340,28 +364,32 @@
 void ps_clean_string(unsigned char *out, const unsigned char *in,
 			int outbuf_size)
 {
-	int rd, wr;
-	char c;
-
-	for (rd = 0, wr = 0 ; wr < outbuf_size; rd++, wr++ ) {
-		c = in[rd];
-		switch (c) {
-			case '(':
-			case ')':
-			case '\\':
-				out[wr] = '\\';
-				out[++wr] = c;
-				break;
-
-			default:
-				out[wr] = c;
-				break;
+        while (outbuf_size > 1 && *in) {
+                if (*in >= '\000' && *in <= '\037') {
+                        *out++ = '^';
+                        outbuf_size--;
+                        if (outbuf_size > 1)
+                                *out++ = *in++ + '@';
+                } else if (*in == '(' || *in == ')' || *in == '\\') {
+                        /* be careful we do not put \ as the last
+                         * character, as it would quote also the PS
+                         * string end character of the actual print
+                         * command */
+                        if (outbuf_size < 3)
+                                *out++ = ' ';
+                        else {
+                                *out++ = '\\';
+                                *out++ = *in++;
+                                outbuf_size--;
 		}
-
-		if (c == 0) {
-			break;
+                } else {
+                        *out++ = *in++;
 		}
+
+                outbuf_size--;
 	}
+
+        *out = '\0';
 }
 
 static