Subject: pkg/28408: Existing patches for a bug in gv breaks functionality
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <hsaliak@kasba.ath.cx>
List: pkgsrc-bugs
Date: 11/24/2004 15:21:01
>Number:         28408
>Category:       pkg
>Synopsis:       Existing patches for a bug in gv breaks functionality
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Nov 24 15:21:00 +0000 2004
>Originator:     Kailash Sethuraman
>Release:        NetBSD 2.0_RC1
>Organization:

>Environment:
	
	
System: NetBSD kasba 2.0_RC1 NetBSD 2.0_RC1 (MYKERN) #0: Sun Oct 17 18:17:47 SGT 2004 hsaliak@kasba:/usr/src/sys/arch/i386/compile/MYKERN i386
Architecture: i386
Machine: i386
>Description:
Patches patch-ag, patch-ah and patch-ai are intended to work around
a security bug in gv as reported in http://www.epita.fr/~bevand_m/asa/asa-0000
However, these patches lead to broken behaviour with gv when opening pdf
files with spaces between them. For example "gv foo\ bar.pdf" leads to 
broken output.
In addition, the page navigation menu is non functional.
This problem has been further discussed at
 http://dero.tamu.edu/netbsdsucks/?action=read-comments&report_id=24 

>How-To-Repeat:
 launch gv on a pdf who's filename contains spaces. 
Eg : gv foo bar.pdf
>Fix:
	I have attached a patch that replaces the system() called used in gv with
a call on execvp(). This is safer and allows the file to contain arbitrary
characters in the file name. Removal of patch-a{g,h,i} is also required after
this patch is applied. This not only fixes the bug in gv that patch-a{g,h,i} 
work around, but  has no side effects. 




$NetBSD$

--- source/ps.c.orig	1997-06-07 06:00:00.000000000 +0800
+++ source/ps.c
@@ -47,6 +47,7 @@
  * 
  */
 #define USE_ACROREAD_WORKAROUND
+#define MAXTOKENS	20
 
 /*
 #define MESSAGES
@@ -58,6 +59,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #ifdef VMS
 #   include <unixio.h>
@@ -337,6 +341,51 @@ int ps_system(cmd)
 }
 #endif
 
+int my_system (char **tokens)
+{
+	pid_t pid  = 0 ;  
+
+	pid = fork();
+	if(pid == 0 ) {
+		execvp("gs",tokens); 
+	}
+	else {
+ 	int retval;
+ 	waitpid(pid,&retval,0);
+	return retval ;
+ 	}
+}
+/* function to place arguments in an argv structure so that my_system 
+   can pass it correctly. The little hack is required so that filenames 
+   with spaces are not parsed as seperate arguments. The goal is fix gv  
+   without major redesign */
+   
+void tokenize(char * tokens[], char * cmd, char * arg1, char * arg2)
+{
+char *p, *s1 , *s2; 
+char * last ; 
+int i = 0; 
+
+for((p=strtok_r(cmd," ",&last)); p;
+    (p=strtok_r(NULL," ",&last)), i++) {
+	/*we stick the filename with the weird characters here */ 
+     if (i < MAXTOKENS ) {  
+		 if(*p == 'X' && (p > cmd) ) {
+			 s1= p;
+		 	--i; 
+		 }
+	 	else if(*p == 'Y'  && (p > cmd) ) {
+			s2=p;
+			--i;
+		}
+		else
+			(tokens)[i] = p; 
+	 }
+	}
+	snprintf(s1-1,strlen(arg1)+1,"%s",arg1); 
+	snprintf(s2-1,strlen(arg2)+1,"%s",arg2); 
+	(tokens)[i] = NULL; /* ready for my_system */
+}
 /*-----------------------------------------------------------*/
 
 static void ps_dynMemExhaust()
@@ -417,13 +466,24 @@ psscan(fileP,filename,filename_raw,filen
       struct document *retval = NULL;
       FILE *tmpfile = (FILE*)NULL;
       char *filename_unc;
+	  char *tokens[MAXTOKENS];
       char cmd[512];
       char s[512];
+	  char tmpfill[512] ;
+	  char tmpfill2[512] ;
+
       filename_unc=file_getTmpFilename(NULL,filename_raw);
-      sprintf(cmd,cmd_uncompress,filename,filename_unc);
+	  memset(tmpfill,'\0',512);
+	  memset(tmpfill2,'\0',512);
+	  memset(tmpfill,'X' ,strlen(filename));
+	  memset (tmpfill2,'Y',strlen(filename_unc));
+	  tmpfill[0]= ' ';
+	  tmpfill2[0]= ' ';
+      snprintf(cmd,512,cmd_uncompress,tmpfill,tmpfill2); 
+	  tokenize(tokens,cmd,filename,filename_unc);
       INFMESSAGE(is compressed)
       INFSMESSAGE(uncompress command,cmd)
-      if (ps_system(cmd) || file_fileIsNotUseful(filename_unc)) {
+      if (my_system(tokens) || file_fileIsNotUseful(filename_unc)) {
 	INFMESSAGE(uncompressing failed)
 unc_exec_failed:
 	sprintf(s,"Execution of\n%s\nfailed.",cmd);
@@ -490,14 +550,26 @@ unc_ok:
       char *filename_dsc;
       char cmd[512];
       char s[512];
+      int i ; 
+      char *tokens[MAXTOKENS];
+      char tmpfill[512],tmpfill2[512];
+
       filename_dsc=file_getTmpFilename(NULL,filename_raw);
-      sprintf(cmd,cmd_scan_pdf,filename,filename_dsc);
+	  memset(tmpfill,'\0',512);
+	  memset(tmpfill2,'\0',512);
+	  memset(tmpfill,'X',strlen(filename));
+	  memset(tmpfill2,'Y',strlen(filename_dsc));
+	  tmpfill[0] = ' ';
+	  tmpfill2[0] = ' '; 
+
+      sprintf(cmd,cmd_scan_pdf,tmpfill,tmpfill2);
+	  tokenize(tokens,cmd,filename,filename_dsc);
       INFMESSAGE(is PDF)
       INFSMESSAGE(scan command,cmd)
 #ifdef VMS
-      if ((system(cmd)&7)!=1 || file_fileIsNotUseful(filename_dsc)) {
+      if ((my_system(tokens)&7)!=1 || file_fileIsNotUseful(filename_dsc)) {
 #else
-      if (system(cmd) || file_fileIsNotUseful(filename_dsc)) {
+      if (my_system(tokens) || file_fileIsNotUseful(filename_dsc)) {
 #endif
 	INFMESSAGE(scan subprocess failed)
 scan_exec_failed: