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: