[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#404235: trr19: segfault when no argument is given



Hello,

Your patch is wrong because you  are using `char *textfile` in the first
snprintf without initializing it. I made a patch which fixes the bug and
works on the Hurd.

Regards,
Arnaud Fontaine

diff -uN trr19-1.0beta5.orig/trr_format.c trr19-1.0beta5/trr_format.c
--- trr19-1.0beta5.orig/trr_format.c	2007-01-21 21:19:23.000000000 +0100
+++ trr19-1.0beta5/trr_format.c	2007-01-21 18:56:58.000000000 +0100
@@ -21,6 +21,11 @@
 #include <signal.h>
 #include <errno.h>
 #include <pwd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "utils.h"
 
 #if defined(HAVE_STRING_H)
 #include <string.h>
@@ -40,12 +45,16 @@
 
 
 main(int argc, char **argv){
-  char textfile[256], formattedfile[256], lockfile[256], *tmpfname;
-  char command[256], line[1024];
+  int err = 0;
   FILE *fd, *tmpfd;
+  size_t len=0;
+  pid_t ret;
   int i;
   struct passwd *pw = NULL;
-
+  int tmpfnamefd = 0;
+  char *textfile = NULL, *lockfile = NULL, *formattedfile = NULL,
+    *command = NULL, *line = NULL;
+  char tmpfname[] = "/tmp/trr_update.XXXXXX";
 
   /* ignore signals */
   signal(SIGHUP, SIG_IGN);
@@ -53,14 +62,16 @@
   signal(SIGQUIT, SIG_IGN);
   signal(SIGTERM, SIG_IGN);
 
-  strcpy(textfile, TEXT_DIR);
-  strcat(textfile, argv[1]);
-  strcpy(formattedfile, textfile);
-  strcat(formattedfile, ".formed");
-  strcpy(lockfile, textfile);
-  strcat(lockfile, ".lock");
+  if(argc < 2){
+    fprintf(stderr, "%s: %s\n", argv[0], strerror (EINVAL));
+    exit(1);
+  }
+
+  my_asprintf(&textfile, "%s%s", TEXT_DIR, argv[1]);
+  my_asprintf(&formattedfile, "%s.formed", textfile);
+  my_asprintf(&lockfile, "%s.lock", textfile);
 
-  umask(18);
+  umask(022);
 
   /* if previous process is formatting same target text,
      wait for that process to finish formatting. */
@@ -81,47 +92,82 @@
 	}
       }
       /* successfully formatted */
-      unlink(lockfile);
-      return 0;
+      exit(0);
     } else{
       perror(lockfile);
       exit(1);
     }
   else{
+    tmpfnamefd = mkstemp(tmpfname);
+
     /* format a text - fork and exec the processes so we can drop privileges */
     switch( fork() ) {
       case -1:          /* Error */
-	perror(fork);
+	perror("fork");
 	exit(1);
 	break;
       case 0:           /* Child */
-	tmpfname = tmpnam(NULL);
 	unlink(formattedfile);
 
 	/* Drop group privileges */
 	pw = getpwuid(getuid());
+	if(!pw){
+	  unlink(lockfile);
+	  fprintf(stderr, "You don't exist..go away\n");
+	  exit(1);
+	}
+
 	setgid(pw->pw_gid);
 
-	sprintf(command, "%s -v '^[ \t]*$' %s | %s 's/\\([.?!;]\\) *$/\\1/' | %s 's/^  *\\(.*\\)$/\\1/' > %s",
-		GREP, textfile, SED, SED, tmpfname);
-	system(command);
+	if (my_asprintf(&command, "%s -v '^[ \t]*$' %s | %s 's/\\([.?!;]\\) *$/\\1/' | %s 's/^  *\\(.*\\)$/\\1/' > %s",
+			GREP, textfile, SED, SED, tmpfname) == -1 || tmpfnamefd == -1)
+	  {
+	    if (tmpfnamefd != -1)
+	      unlink(lockfile);
+
+	    perror("temporary file creation");
+	    exit(1);
+	  }
+	
+	execl("/bin/sh", "sh", "-c", command);
 	break;
       default:          /* Parent */
+	do
+	  ret = wait (NULL);
+	while (!(ret == -1 && errno == ECHILD));
 	break;
     }
 
-    tmpfd = fopen(tmpfname, "r");
+    unlink(tmpfname);
+    tmpfd = fdopen(tmpfnamefd, "r");
+    if (!tmpfd){
+      unlink(lockfile);
+      perror("fopen");
+      exit(1);
+    }
+	
     fd = fopen(formattedfile, "w");
-
-    while(fgets(line, 1024, tmpfd))
+    if (!fd){
+      unlink(lockfile);
+      perror("fopen");
+      exit(1);
+    }
+	
+    while(my_getline(&line, &len, tmpfd) != -1)
       fputs(line, fd);
 
+    /* release lock */
+    unlink(lockfile);
+
+    free(line);
+    free(command);
+    free(formattedfile);
+    free(textfile);
+    free(lockfile);
+
     fclose(tmpfd);
     fclose(fd);
-    unlink(tmpfname);
 
-    /* release lock */
-    unlink(lockfile);
-    return 0;
+    return err;
   }
 }
diff -uN trr19-1.0beta5.orig/trr_update.c trr19-1.0beta5/trr_update.c
--- trr19-1.0beta5.orig/trr_update.c	2007-01-21 21:19:23.000000000 +0100
+++ trr19-1.0beta5/trr_update.c	2007-01-21 21:18:12.000000000 +0100
@@ -21,6 +21,9 @@
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
+#include <time.h>
+
+#include "utils.h"
 
 #if defined(HAVE_STRING_H)
 #include <string.h>
@@ -45,9 +48,12 @@
 #endif /* HAVE_FCNTL_H */
 
 main(int argc, char **argv){
-  char scorefile[256], lockfile[256], datestr[64];
-  char line[256], savedline[256];
-  const char *user, *scores, *step, *times, *ttime, *token;
+  char *scorefile = NULL, *lockfile = NULL, *line = NULL, *savedline = NULL;
+  char *user = NULL, *scores = NULL, *step = NULL, *times = NULL,
+    *ttime = NULL, *token = NULL;
+  size_t len=0;
+  char datestr[64];
+
   FILE *fd, *tmpf;
   int score, tmpscore, i, myself, inserted;
   long datev;
@@ -59,12 +65,16 @@
   signal(SIGTERM, SIG_IGN);
 
   umask(18);
-  strcpy(scorefile, RECORD_DIR);
+
+  if (argc < 7){
+    fprintf(stderr, "too few arguments\n");
+    exit(1);
+  }
+
+  my_asprintf (&scorefile, "%s%s", RECORD_DIR, argv[1]);
 
   /* create a new record file */
   if (argc == 2){
-    strcat(scorefile, argv[1]);
-
     if ((fd = fopen(scorefile, "w")) == NULL){
       perror(scorefile);
       exit(1);
@@ -73,10 +83,9 @@
     exit(0);
   }
 
-  /* upfate high score file */
-  strcat(scorefile, argv[1]);
-  strcpy(lockfile, scorefile);
-  strcat(lockfile, ".lock");
+  /* update high score file */
+  my_asprintf(&lockfile, "%s.lock", scorefile);
+
   user = argv[2];
   scores = argv[3];
   score = atoi(argv[3]);
@@ -110,13 +119,19 @@
   inserted = 0;
 
   /* sorting ... */
-  while (fgets(line, 256, fd)){
+  while (my_getline(&line, &len, fd) != -1){
     myself = 0;
-    strcpy(savedline, line);
-    token = (char*)strtok(line, " \t");
-    if (! strcmp(user, token))
+    savedline = strdup(line);
+    token = strtok(line, " \t");
+    if (token && !strcmp(user, token))
       myself = 1;
-    token = (char*)strtok(NULL, " \t");
+
+    token = strtok(NULL, " \t");
+    if (!token){
+      perror("strok");
+      exit(1);
+    }
+
     tmpscore = atoi(token);
     if ((! inserted) && (tmpscore <= score)){
       inserted = 1;
@@ -146,12 +161,18 @@
     unlink(lockfile);
     exit(1);
   }
-  while (fgets(line, 256, tmpf))
+  while (my_getline(&line, &len, tmpf) != -1)
     fputs(line, fd);
 
   fclose(tmpf);
   fclose(fd);
 
+  free(line);
+  free(lockfile);
+  free(scorefile);
+  free(savedline);
+  free(token);
+
   /* release lock */
   unlink(lockfile);
   return 0;
Les fichiers binaires trr19-1.0beta5.orig/trr_update.o et trr19-1.0beta5/trr_update.o sont différents.
diff -uN trr19-1.0beta5.orig/utils.c trr19-1.0beta5/utils.c
--- trr19-1.0beta5.orig/utils.c	1970-01-01 01:00:00.000000000 +0100
+++ trr19-1.0beta5/utils.c	2007-01-21 14:39:46.000000000 +0100
@@ -0,0 +1,98 @@
+/* utils.c -- utils functions for trr19 
+ * Last modified on Sun Jan 01 01:10:21 2007
+ * Copyright (C) 2007 Arnaud Fontaine <arnaud@andesi.org>
+ */
+
+/* This file is a part of TRR19, a type training software on
+ * GNU Emacs.
+ *
+ * You can redistribute it and/or modify it under the terms of
+ * the version 2 of GNU General Public License as published by the
+ * Free Software Foundation.
+ *
+ * TRR19 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __GLIBC__
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "utils.h"
+
+ssize_t my_getline(char **lineptr, size_t *n, FILE *stream)
+{
+  char *ret = NULL;
+
+  if(lineptr == NULL || n == NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if(*n == 0)
+    {
+      *lineptr = malloc(CHUNK_SIZE);
+      *n = CHUNK_SIZE;
+    }
+
+  ret = fgets (*lineptr, *n, stream);
+  while(ret != NULL && (*lineptr)[strlen (*lineptr) - 1] != '\n')
+    {
+      *n += CHUNK_SIZE;
+      *lineptr = realloc(*lineptr, *n);
+
+      ret = fgets(*lineptr + strlen (*lineptr), CHUNK_SIZE, stream);
+    }
+
+  if (ret == NULL)
+    return -1;
+
+  return strlen (*lineptr);
+}
+
+int my_asprintf(char **str, const char *fmt, ...)
+{
+  int size;
+  va_list ap;
+  int n;
+
+  if(*str == NULL)
+    {
+      *str = malloc(CHUNK_SIZE);
+      if (*str == NULL)
+	return -1;
+
+      size = CHUNK_SIZE;
+    }
+  else
+    size = strlen (*str);
+
+  va_start (ap, fmt);
+  n = vsnprintf (*str, size, fmt, ap);
+
+  while (n >= size)
+    {
+      size += CHUNK_SIZE;
+      *str = realloc(*str, size);
+      if (*str == NULL)
+	{
+	  errno = ENOMEM;
+	  return -1;
+	}
+
+      n = vsnprintf (*str, size, fmt, ap);
+    }
+
+  va_end (ap);
+
+  return n;
+}
+
+#endif
diff -uN trr19-1.0beta5.orig/utils.h trr19-1.0beta5/utils.h
--- trr19-1.0beta5.orig/utils.h	1970-01-01 01:00:00.000000000 +0100
+++ trr19-1.0beta5/utils.h	2007-01-21 20:43:31.000000000 +0100
@@ -0,0 +1,34 @@
+/* utils.h -- header for utils functions for trr19 
+ * Last modified on Sun Jan 01 01:10:21 2007
+ * Copyright (C) 2007 Arnaud Fontaine <arnaud@andesi.org>
+ */
+
+/* This file is a part of TRR19, a type training software on
+ * GNU Emacs.
+ *
+ * You can redistribute it and/or modify it under the terms of
+ * the version 2 of GNU General Public License as published by the
+ * Free Software Foundation.
+ *
+ * TRR19 is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#define CHUNK_SIZE 4096
+
+/* GLibc provides  getline and asprintf,  which allocate automatically
+   the memory and replaces respectively fgets and sprintf */
+#ifdef __GLIBC__
+# define my_getline getline
+# define my_asprintf asprintf
+#else
+ssize_t my_getline(char **lineptr, size_t *n, FILE *stream);
+int my_asprintf(char **str, const char *fmt, ...);
+#endif /* !__GLIBC__ */
+
+#endif
Les fichiers binaires trr19-1.0beta5.orig/utils.o et trr19-1.0beta5/utils.o sont différents.

Reply to: