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;
}