tag 645839 + patch
thanks

I wrote :
> apt-spy: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char 
> *)
> &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, 
> fd))))
> && old_size == 0) || ((unsigned long) (old_size) >= (unsigned
> long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *
> (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size 
> &
> 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
> Aborted

I worked on it and found several problems, in the files main.c parse.c and 
file.c,
mainly with memory allocation, that I tried to solve.
Finally, I think that I succeed. The attached patch should bypass a lot of 
segfaults.
It should close this bug, bug #491802, and maybe other segmentation fault bugs.
(#447232? #427561?)

Any one to test it ?

-- 
Laurent Dard
--- apt-spy-3.1.orig/main.c
+++ apt-spy-3.1/main.c
@@ -49,7 +49,7 @@
 int main(int argc, char *argv[])
 {
 	int c;
-	char *cur_entry; /* Entry we are benchmarking */
+	char *cur_entry = NULL; /* Entry we are benchmarking */
 
 	char *distrib = NULL; /* distribution to use. */
 	char *mirror_list = NULL; /* mirror list file */
@@ -63,35 +63,38 @@
 	char *update_url = NULL; /* URL to use for updating */
 	char *country_list = NULL; /* List of countries to b/m */
 	char *section_list = NULL; /* List of section to include */
-	FILE *infile_p, *outfile_p;	/* input/output file pointers */
-	FILE *config_p; /* config file pointer */
-	FILE *mirror_p; /* mirror list pointer */
-	FILE *topfile_p;
+	FILE *infile_p = NULL;	/* input file pointer */
+	FILE *outfile_p = NULL;	/* output file pointer */
+	FILE *config_p = NULL; /* config file pointer */
+	FILE *mirror_p = NULL; /* mirror list pointer */
+	FILE *topfile_p = NULL;
 	int timeout = 15; /* time to benchmark each server */
-	int toplist = 0; /* Whether to write toplist. */
 	int argsCount = 0; /* persistent counter for args */
 	char *args[100]; /* persistent args array */
-	char str[100] = "";
-	int i; 
+	char str[4] = "-? "; /* short option string */
 	/* Number of servers to test. If negative, test them all. */
 	int test_number = -1;		
 
 	/* Server information structures. */
-	server_t current, *best;
+	server_t current;
+	server_t *best = NULL;
+
+	/* Initialization of the persistent args array */
+	memset(args,0,100);
 
 	/* Parse options... */
 	while((c = getopt(argc, argv, "y:a:c:d:e:f:i:m:o:p:s:t:u:w:n:vh")) != -1)
 	{
-		for(i = 0; i < 100; i++)
-			str[i] = '\0';
-		strcpy(str,"");
-		str[0] = '-'; str[1] = c; str[2] = ' ';
-		strcat(str, optarg);
-		args[argsCount] = (char *)malloc(strlen(str));
-		strcpy(args[argsCount],str);
-		argsCount++;
+		if (optarg) { /* not set with -h */
+			str[1] = c;
+			args[argsCount] = malloc(strlen(str)+strlen(optarg)+1);
+			memset(args[argsCount],0,strlen(str)+strlen(optarg)+1);
+			strncpy(args[argsCount],str,strlen(str));
+			strncat(args[argsCount],optarg,strlen(optarg));
+			argsCount++;
+		}
 		switch(c) {
-		char *end;
+		char *end = NULL;
 		 /* Sections to include into apt-source */
 		case 'y':
 			section_list = optarg;
@@ -158,7 +161,6 @@
 			break;
 		/* Should we write a list of the "top" servers? */
 		case 'w':
-			toplist = 1;
 			topfile = optarg;
 			break;
 		/* Number of servers to write in "top" server list */
@@ -178,6 +180,7 @@
 		case 'h':
 		default:
 			usage();			/* display help */
+			break;
 		}
 	}	
 	argc -= optind;
@@ -194,6 +197,9 @@
 		exit(1);
 	}
 
+	/* Zero the "best" structure */
+	memset(best, 0, sizeof(server_t) * (BESTNUMBER + 1));
+
 	/* We require an area and distribution argument if we are not updating */
 	if ((argc == 0) && (distrib == NULL))
 		usage();
@@ -240,7 +246,6 @@
 	/* argc should be 0. If not, there's something wrong. */
 	if (argc != 0)
 		usage();
-	                                
 
 	/* We open the infile. Either a temporary file, or a user-specified 
 	   one. */
@@ -297,15 +302,10 @@
 			}
 		}
 	}
-			
 	
 	/* Make sure we're at the beginning... */
 	rewind(infile_p);
 
-	/* Zero the "best" structure */
-	for (c = 0; c < BESTNUMBER; c++)
-		memset(&best[c], 0, sizeof(server_t));
-
 	/* This is the main loop. It'll exit when we've exhausted the URL 
 	   list or test_number is 0 */
 
--- apt-spy-3.1.orig/parse.c
+++ apt-spy-3.1/parse.c
@@ -23,10 +23,10 @@
 
 int build_area_file(FILE *config_p, FILE *infile_p, FILE *mirror_list, char *area)
 {
-	char *line;		/* Where we read the lines into */
-	char *tmp;		/* Temp. pointer */
-	char *inputline;	/* The line that will be written to config_p */
-	char *country_code;	/* where we put the country code */
+	char *line = NULL;		/* Where we read the lines into */
+	char *tmp = NULL;		/* Temp. pointer */
+	char *inputline = NULL;		/* The line that will be written to config_p */
+	char *country_code = NULL;	/* where we put the country code */
 
 	/* Uppercase area */
 	str_toupper(area);
@@ -77,13 +77,26 @@
 		
 		/* If country_code points to a '\n', there were no other characters. It was a blank line. */
 		/* If it points to a '#', there is a comment. We skip it too. */
-		if ((*country_code == '\n') || (*country_code == '#'))
+		if ((*country_code == '\n') || (*country_code == '#')) {
+			free(line);
 			continue;
+		}
 
-		if ((strchr(line, ':')) != NULL)
+		if ((strchr(line, ':')) != NULL) {
+			free(line);
 			return 0;			/* End of list. Return. */
+		}
 
 		/* We do a little fiddling to get the country code down to 2 letters and a space */
+		/* but before we must add 1 or 2 bytes to the allocated memory if it's too small.
+		   The line can be only one char: users may do silly things sometimes... */
+		if (strlen(country_code) < 3) {
+			line = realloc(line,strlen(line)+4-strlen(country_code));
+			if (line == NULL) {
+				perror("realloc");
+				exit(1);
+			}
+		}
 		*(country_code + 2) = ' ';
 		*(country_code + 3) = '\0';
 
@@ -97,6 +110,8 @@
 			continue;
 		}
 
+		free(line);
+
 		/* The next read of infile_p will return the first mirror entry. We parse */
 		/* this and build a line to put into the temporary file. */
 
@@ -106,13 +121,9 @@
 			fputs(inputline, infile_p);
 			free(inputline);
 
-			if ((ferror(infile_p)) != 0) { 	/* Check for file error */
-				free(line);
+			if ((ferror(infile_p)) != 0) 	/* Check for file error */
 				return 1;
-			}
 		}
-
-		free(line);
 	}
 	return 0;
 }
@@ -186,7 +197,9 @@
 
 int find_country(FILE *mirror_list, char *country_code)
 {
-	char *line, *cc;
+	char *line =NULL;
+	char *cc =NULL;
+	char *tmp =NULL;	/* Temp. pointer */
 
 	/* Make sure we're at beginning of file */
 	rewind(mirror_list);
@@ -199,27 +212,29 @@
 	while ((line = next_entry(mirror_list)) != NULL) {
 
 		cc = strstr(line, country_code);
-		if (cc == NULL)
+		if (cc == NULL) {
+			free(line);
 			continue;
-			
+		}
+
 		/* Skip white space */
-		while (isspace(*line))
-			++line;
-		
+		tmp = line;
+		while (isspace(*tmp))
+			++tmp;
 		/* Country code should be first two characters on line. */
-		if (cc == line)		
+		if (cc == tmp)
 			break;
 	}
 
 	if (line == NULL)
 		return 1;
+	free(line);
 	
-	next_entry(mirror_list);		/* Skip a line */
-	
-	if (ferror(mirror_list)) {
-		free(line);
+	line = next_entry(mirror_list);		/* Skip a line */
+	if (!line) {
 		return 1;
 	}
+	free(line);
 	return 0;		/* We're positioned nicely for the next read */
 }
 
@@ -235,6 +250,11 @@
 	/* First, we read in a line from the file */
 	save_line = line = next_entry(mirror_list);
 
+	if (line == NULL) {
+		perror("malloc");
+		exit(1);
+	}
+
 	/* Allocate space for creation */
 	len=5+strlen(line);
 	save_creation = creation = malloc(len);
@@ -247,12 +267,14 @@
 	/* test for file error */
 	if (ferror(mirror_list)) {
 		perror("fopen");
+		free(line);
 		free(save_creation);
 		return NULL;
 	}
 	
 	/* If the line begins with a space, we assume it is empty and the list is exhausted. */
 	if (isspace(*line) != 0) {
+		free(line);
 		free(save_creation);
 		return NULL;
 	}
@@ -301,7 +323,6 @@
 void tokenise(server_t *current, char *cur_entry)
 {
 	char *temp;	/* We use this for temporary string-pointing :P */
-	static char null_string[]="";
 
 	/* We initialise the structure to 0 */
 	memset(current, 0, sizeof(*current));
@@ -341,7 +362,7 @@
 			perror("malloc");
 			exit(1);
 		}
-	} else current->path[FTP]=null_string;
+	} else current->path[FTP]=strdup("");
 
 	/* And now check for HTTP entry */
 	if (*(++cur_entry) != ':') {
@@ -360,7 +381,7 @@
 			perror("realloc");
 			exit(1);
 		}
-	} else current->path[HTTP]=null_string;
+	} else current->path[HTTP]=strdup("");
 
 	/* We're done for now */
 }
@@ -426,7 +447,7 @@
 int write_top(FILE *infile_p, FILE *outfile_p, server_t *best)
 {
 	int i = 0;
-	char *line;
+	char *line = NULL;
 	
 	while (i < BESTNUMBER) {
 	
@@ -438,8 +459,10 @@
 			if (best[i].hostname != NULL && 
 			    strstr(line, best[i].hostname) != NULL) {	/* Check for hostname */
 				fputs(line, outfile_p);		/* if it's there, write to file */
+				free(line);
 				break;
 			}
+			free(line);
 		}
 		
 		if ((ferror(infile_p) != 0) || (ferror(outfile_p) != 0))
--- apt-spy-3.1.orig/file.c
+++ apt-spy-3.1/file.c
@@ -77,12 +77,17 @@
 
 char *next_entry(FILE *infile_p)
 {
-	char *temp;
-	unsigned long orig_position, buffsize;
+	char *temp = NULL;
+	long int orig_position = 0;
+	long int buffsize = 0;
 	int c;
 
 	/* Save original file position */
 	orig_position = ftell(infile_p);
+	if (orig_position < 0) {
+		perror("Input error (ftell)");
+		exit(1);
+	}
 
 	/* Fast-forward to new line */
 	while ((c = getc(infile_p)) != '\n') {
@@ -92,7 +97,13 @@
 		}
 	}
 
-	buffsize = ftell(infile_p) - orig_position;	/* Calculate buffer size */
+	/* Calculate buffer size */
+	buffsize = ftell(infile_p);
+	if (buffsize < 0) {
+		perror("Input error (ftell)");
+		exit(1);
+	}
+	buffsize -= orig_position;
 	
 	/* create storage space for line */
 	temp = malloc(buffsize + 1);
@@ -103,10 +114,16 @@
 	}
 
 	/* Rewind file to original position */
-	fseek(infile_p, orig_position, SEEK_SET);
+	if (fseek(infile_p, orig_position, SEEK_SET) != 0) {
+		perror("Input error (fseek)");
+		exit(1);
+	}
 
 	/* We now read the line into the newly created buffer */
-	fgets(temp, buffsize + 1, infile_p);
+	if (!fgets(temp, buffsize + 1, infile_p)) {
+		perror("Input error (fseek)");
+		exit(1);
+	}
 
 	return temp;
 }

Reply via email to