title: Using realloc to expand buffer while reading from file crashes
body: <p>I am writing some code that needs to read <a href="http://en.wikipedia.org/wiki/FASTA_format" rel="noreferrer">fasta files</a>, so part of my code (included below) is a fasta parser. As a single sequence can span multiple lines in the fasta format, I need to concatenate multiple successive lines read from the file into a single string. I do this, by realloc'ing the string buffer after reading every line, to be the current length of the sequence plus the length of the line read in. I do some other stuff, like stripping white space etc. All goes well for the first sequence, but fasta files can contain multiple sequences. So similarly, I have a dynamic array of structs with a two strings (title, and actual sequence), being "char *". Again, as I encounter a new title (introduced by a line beginning with '>') I increment the number of sequences, and realloc the sequence list buffer. The realloc segfaults on allocating space for the second sequence with</p>
  
  <pre><code>*** glibc detected *** ./stackoverflow: malloc(): memory corruption: 0x09fd9210 ***
  Aborted
  </code></pre>
  
  <p>For the life of me I can't see why. I've run it through gdb and everything seems to be working (i.e. everything is initialised, the values seems sane)... Here's the code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;ctype.h&gt;
  #include &lt;math.h&gt;
  #include &lt;errno.h&gt;
  
  //a struture to keep a record of sequences read in from file, and their titles
  typedef struct {
      char *title;
      char *sequence;
  } sequence_rec;
  
  //string convenience functions
  
  //checks whether a string consists entirely of white space
  int empty(const char *s) {
      int i;
      i = 0;
      while (s[i] != 0) {
          if (!isspace(s[i])) return 0;
          i++;
      }
      return 1;
  }
  
  //substr allocates and returns a new string which is a substring of s from i to
  //j exclusive, where i &lt; j; If i or j are negative they refer to distance from
  //the end of the s
  char *substr(const char *s, int i, int j) {
      char *ret;
      if (i &lt; 0) i = strlen(s)-i;
      if (j &lt; 0) j = strlen(s)-j;
      ret = malloc(j-i+1);
      strncpy(ret,s,j-i);
      return ret;
  }
  
  //strips white space from either end of the string
  void strip(char **s) {
      int i, j, len;
      char *tmp = *s;
      len = strlen(*s);
      i = 0;
      while ((isspace(*(*s+i)))&amp;&amp;(i &lt; len)) {
          i++;
      }
      j = strlen(*s)-1;
      while ((isspace(*(*s+j)))&amp;&amp;(j &gt; 0)) {
          j--;
      }
      *s = strndup(*s+i, j-i);
      free(tmp);
  }
  
  
  int main(int argc, char**argv) {
      sequence_rec *sequences = NULL;
      FILE *f = NULL;
      char *line = NULL;
      size_t linelen;
      int rcount;
      int numsequences = 0;
  
      f = fopen(argv[1], "r");
      if (f == NULL) {
          fprintf(stderr, "Error opening %s: %s\n", argv[1], strerror(errno));
          return EXIT_FAILURE;
      }
      rcount = getline(&amp;line, &amp;linelen, f);
      while (rcount != -1) {
          while (empty(line)) rcount = getline(&amp;line, &amp;linelen, f);
          if (line[0] != '&gt;') {
              fprintf(stderr,"Sequence input not in valid fasta format\n");
              return EXIT_FAILURE;
          }
  
          numsequences++;
          sequences = realloc(sequences,sizeof(sequence_rec)*numsequences);
          sequences[numsequences-1].title = strdup(line+1); strip(&amp;sequences[numsequences-1].title);
          rcount = getline(&amp;line, &amp;linelen, f);
          sequences[numsequences-1].sequence = malloc(1); sequences[numsequences-1].sequence[0] = 0;
          while ((!empty(line))&amp;&amp;(line[0] != '&gt;')) {
              strip(&amp;line);
              sequences[numsequences-1].sequence = realloc(sequences[numsequences-1].sequence, strlen(sequences[numsequences-1].sequence)+strlen(line)+1);
              strcat(sequences[numsequences-1].sequence,line);
              rcount = getline(&amp;line, &amp;linelen, f);
          }
      }
      return EXIT_SUCCESS;
  }
  </code></pre>