The following patches fix two security bugs:
1. buffer overflows (CAN-2004-0234)
2. directory traversal problems (CAN-2004-0235)
3. symlink vulnerability

--- src/header.c.orig	2000-10-05 19:36:03.000000000 +0200
+++ src/header.c	2004-04-21 14:30:52.000000000 +0200
@@ -538,6 +538,10 @@
 				/*
 				 * filename
 				 */
+				if (header_size >= 256) {
+				  fprintf(stderr, "Possible buffer overflow hack attack, type #1\n");
+				  exit(109);
+				}
 				for (i = 0; i < header_size - 3; i++)
 					hdr->name[i] = (char) get_byte();
 				hdr->name[header_size - 3] = '\0';
@@ -547,6 +551,10 @@
 				/*
 				 * directory
 				 */
+				if (header_size >= FILENAME_LENGTH) {
+				  fprintf(stderr, "Possible buffer overflow hack attack, type #2\n");
+				  exit(110);
+				}
 				for (i = 0; i < header_size - 3; i++)
 					dirname[i] = (char) get_byte();
 				dirname[header_size - 3] = '\0';
--- src/lhext.c.orig	2000-10-04 16:57:38.000000000 +0200
+++ src/lhext.c	2004-04-21 14:30:52.000000000 +0200
@@ -190,8 +190,13 @@
 		q = (char *) rindex(hdr->name, '/') + 1;
 	}
 	else {
+		if (is_directory_traversal(q)) {
+		  fprintf(stderr, "Possible directory traversal hack attempt in %s\n", q);
+		  exit(111);
+		}
+
 		if (*q == '/') {
-			q++;
+			while (*q == '/') { q++; }
 			/*
 			 * if OSK then strip device name
 			 */
@@ -419,6 +424,33 @@
 	return;
 }
 
+int
+is_directory_traversal(char *string)
+{
+  unsigned int type = 0; /* 0 = new, 1 = only dots, 2 = other chars than dots */
+  char *temp;
+
+  temp = string;
+
+  while (*temp != 0) {
+    if (temp[0] == '/') {
+      if (type == 1) { return 1; }
+      type = 0;
+      temp++;
+      continue;
+    }
+
+    if ((temp[0] == '.') && (type < 2))
+      type = 1;
+    if (temp[0] != '.')
+      type = 2;
+
+    temp++;
+  } /* while */
+
+  return (type == 1);
+}
+
 /* Local Variables: */
 /* mode:c */
 /* tab-width:4 */
--- src/lhext.c.symlink	2000-10-04 10:57:38.000000000 -0400
+++ src/lhext.c	2003-05-19 22:55:57.000000000 -0400
@@ -351,6 +351,7 @@ extract_one(afp, hdr)
 				}
 
 				unlink(bb1);
+				make_parent_path(bb1);
 				l_code = symlink(bb2, bb1);
 				if (l_code < 0) {
 					if (quiet != TRUE)
################################################################
The following patches are fixing the following Security bugs:
Fixed multiple vulnerabilities; bug #62618 from GenToo
Gentoo Linux Security Advisory                           GLSA 200409-13
CAN-2004-0694, CAN-2004-0745, CAN-2004-0769, CAN-2004-0771
################################################################
Index: src/lha.h
--- src/lha.h.orig	2000-10-05 19:35:38 +0200
+++ src/lha.h	2004-09-20 14:59:52 +0200
@@ -16,6 +16,7 @@
 #include <sys/types.h>
 #include <sys/file.h>
 #include <sys/stat.h>
+#include <stdlib.h>
 
 #include <signal.h>
 
Index: src/lha_macro.h
--- src/lha_macro.h.orig	2000-10-04 16:57:38 +0200
+++ src/lha_macro.h	2004-09-20 14:59:52 +0200
@@ -53,7 +53,7 @@
 #define SEEK_SET		0
 #define SEEK_CUR		1
 #define SEEK_END		2
-#endif	/* SEEK_SET
+#endif	/* SEEK_SET */
 
 
 /* non-integral functions */
Index: src/lharc.c
--- src/lharc.c.orig	2000-10-05 19:33:34 +0200
+++ src/lharc.c	2004-09-20 14:59:52 +0200
@@ -830,9 +830,10 @@
 	DIRENTRY       *dp;
 	struct stat     tmp_stbuf, arc_stbuf, fil_stbuf;
 
-	strcpy(newname, name);
+	strncpy(newname, name, sizeof(newname));
+	newname[sizeof(newname)-1] = 0;
 	len = strlen(name);
-	if (len > 0 && newname[len - 1] != '/')
+	if (len > 0 && newname[len - 1] != '/' && len < (sizeof(newname)-1))
 		newname[len++] = '/';
 
 	dirp = opendir(name);
@@ -846,6 +847,11 @@
 
 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
 		n = NAMLEN(dp);
+		if (len >= (sizeof(newname)-1) ||
+				(len+n) >= (sizeof(newname)-1) ||
+					 n  <= 0                   ||
+				(len+n) <= 0)
+			break;
 		strncpy(newname + len, dp->d_name, n);
 		newname[len + n] = '\0';
 		if (GETSTAT(newname, &fil_stbuf) < 0)
@@ -903,7 +909,8 @@
 		strcpy(temporary_name, TMP_FILENAME_TEMPLATE);
 	}
 	else {
-		sprintf(temporary_name, "%s/lhXXXXXX", extract_directory);
+		snprintf(temporary_name, sizeof(temporary_name),
+			"%s/lhXXXXXX", extract_directory);
 	}
 #ifdef MKSTEMP
 	mkstemp(temporary_name);
@@ -913,10 +920,16 @@
 #else
 	char           *p, *s;
 
-	strcpy(temporary_name, archive_name);
+	strncpy(temporary_name, archive_name, sizeof(temporary_name));
+	temporary_name[sizeof(temporary_name)-1] = 0;
 	for (p = temporary_name, s = (char *) 0; *p; p++)
 		if (*p == '/')
 			s = p;
+
+	if( sizeof(temporary_name) - ((size_t) (s-temporary_name)) - 1
+		<= strlen("lhXXXXXX"))
+			exit(-1);
+
 	strcpy((s ? s + 1 : temporary_name), "lhXXXXXX");
 #ifdef MKSTEMP
 	mkstemp(temporary_name);
@@ -1052,7 +1065,8 @@
 
 	if (open_old_archive_1(archive_name, &fp))
 		return fp;
-	sprintf(expanded_archive_name, "%s.lzh", archive_name);
+	snprintf(expanded_archive_name, sizeof(expanded_archive_name),
+		"%s.lzh", archive_name);
 	if (open_old_archive_1(expanded_archive_name, &fp)) {
 		archive_name = expanded_archive_name;
 		return fp;
@@ -1061,7 +1075,8 @@
 	 * if ( (errno&0xffff)!=E_PNNF ) { archive_name =
 	 * expanded_archive_name; return NULL; }
 	 */
-	sprintf(expanded_archive_name, "%s.lzs", archive_name);
+	snprintf(expanded_archive_name, sizeof(expanded_archive_name),
+		"%s.lzs", archive_name);
 	if (open_old_archive_1(expanded_archive_name, &fp)) {
 		archive_name = expanded_archive_name;
 		return fp;
Index: src/lhext.c
--- src/lhext.c.orig	2004-09-20 14:59:52 +0200
+++ src/lhext.c	2004-09-20 14:59:52 +0200
@@ -82,7 +82,8 @@
 	register char  *p;
 
 	/* make parent directory name into PATH for recursive call */
-	strcpy(path, name);
+	memset(path, 0, sizeof(path));
+	strncpy(path, name, sizeof(path)-1);
 	for (p = path + strlen(path); p > path; p--)
 		if (p[-1] == '/') {
 			*--p = '\0';
@@ -212,9 +213,11 @@
 	}
 
 	if (extract_directory)
-		sprintf(name, "%s/%s", extract_directory, q);
-	else
-		strcpy(name, q);
+		snprintf(name, sizeof(name), "%s/%s", extract_directory, q);
+	else {
+		strncpy(name, q, sizeof(name));
+		name[sizeof(name) - 1] = '\0';
+	}
 
 
 	/* LZHDIRS_METHODを持つヘッダをチェックする */
@@ -335,7 +338,8 @@
 			if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK) {
 				char            buf[256], *bb1, *bb2;
 				int             l_code;
-				strcpy(buf, name);
+				strncpy(buf, name, sizeof(buf));
+				buf[sizeof(buf)-1] = 0;
 				bb1 = strtok(buf, "|");
 				bb2 = strtok(NULL, "|");
 
@@ -365,9 +369,10 @@
 				if (quiet != TRUE) {
 					printf("Symbolic Link %s -> %s\n", bb1, bb2);
 				}
-				strcpy(name, bb1);	/* Symbolic's name set */
+				strncpy(name, bb1, 255);	/* Symbolic's name set */
+				name[255] = 0;
 #else
-				sprintf(buf, "%s -> %s", bb1, bb2);
+				sprintf(buf, sizeof(buf), "%s -> %s", bb1, bb2);
 				warning("Can't make Symbolic Link", buf);
 				return;
 #endif
Index: src/lhlist.c
--- src/lhlist.c.orig	2000-10-04 16:57:38 +0200
+++ src/lhlist.c	2004-09-20 14:59:52 +0200
@@ -250,7 +250,8 @@
 			printf(" %s", hdr->name);
 		else {
 			char            buf[256], *b1, *b2;
-			strcpy(buf, hdr->name);
+			strncpy(buf, hdr->name, sizeof(buf));
+			buf[sizeof(buf)-1] = 0;
 			b1 = strtok(buf, "|");
 			b2 = strtok(NULL, "|");
 			printf(" %s -> %s", b1, b2);
Index: src/util.c
--- src/util.c.orig	2000-10-04 16:57:38 +0200
+++ src/util.c	2004-09-20 14:59:52 +0200
@@ -276,21 +276,27 @@
 	char           *path;
 {
 	int             stat, rtn = 0;
-	char           *cmdname;
-	if ((cmdname = (char *) malloc(strlen(RMDIRPATH) + 1 + strlen(path) + 1))
-	    == 0)
+	pid_t           child;
+
+
+	/* XXX thomas: shell meta chars in path could exec commands */
+	/* therefore we should avoid using system() */
+	if ((child = fork()) < 0)
+		return (-1);    /* fork error */
+	else if (child) {       /* parent process */
+		while (child != wait(&stat))    /* ignore signals */
+			continue;
+	}
+	else {                  /* child process */
+		execl(RMDIRPATH, "rmdir", path, (char *) 0);
+		/* never come here except execl is error */
 		return (-1);
-	strcpy(cmdname, RMDIRPATH);
-	*(cmdname + strlen(RMDIRPATH)) = ' ';
-	strcpy(cmdname + strlen(RMDIRPATH) + 1, path);
-	if ((stat = system(cmdname)) < 0)
-		rtn = -1;	/* fork or exec error */
-	else if (stat) {	/* RMDIR command error */
-		errno = EIO;
-		rtn = -1;
 	}
-	free(cmdname);
-	return (rtn);
+	if (stat != 0) {
+		errno = EIO;    /* cannot get error num. */
+		return (-1);
+	}
+	return (0);
 }
 
 /* ------------------------------------------------------------------------ */
Index: src/header.c
--- src/header.c.orig	2004-09-20 14:59:52 +0200
+++ src/header.c	2004-09-20 14:59:52 +0200
@@ -656,8 +656,17 @@
 	}
 
 	if (dir_length) {
+		if ((dir_length + name_length) > sizeof(dirname)) {
+			fprintf(stderr, "Insufficient buffer size\n");
+			exit(112);
+		}
 		strcat(dirname, hdr->name);
-		strcpy(hdr->name, dirname);
+
+		if ((dir_length + name_length) > sizeof(hdr->name)) {
+			fprintf(stderr, "Insufficient buffer size\n");
+			exit(112);
+		}
+		strncpy(hdr->name, dirname, sizeof(hdr->name));
 		name_length += dir_length;
 	}
 
