Subject: Memory Leak in coreutils/lib/localcharset.c

From: Zhaopeng Li <[email-masked]>
Date: Tue, 13 Jan 2015 18:31:18 +0800

At line 221, the assignment (old_res_ptr = res_ptr) will lead to memory leak when iteration of corresponding loop is greater than 3.

 189 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l189>                   /* Parse the file's contents.  */
 190 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l190>                   char *res_ptr = NULL;
 191 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l191>                   size_t res_size = 0;
 192 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l192> 
 193 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l193>                   for (;;)
 194 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l194>                     {
 195 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l195>                       int c;
 196 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l196>                       char buf1[50+1];
 197 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l197>                       char buf2[50+1];
 198 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l198>                       size_t l1, l2;
 199 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l199>                       char *old_res_ptr;
 200 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l200> 
 201 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l201>                       c = getc (fp);
 202 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l202>                       if (c == EOF)
 203 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l203>                         break;
 204 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l204>                       if (c == '\n' || c == ' ' || c == '\t')
 205 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l205>                         continue;
 206 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l206>                       if (c == '#')
 207 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l207>                         {
 208 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l208>                           /* Skip comment, to end of line.  */
 209 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l209>                           do
 210 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l210>                             c = getc (fp);
 211 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l211>                           while (!(c == EOF || c == '\n'));
 212 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l212>                           if (c == EOF)
 213 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l213>                             break;
 214 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l214>                           continue;
 215 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l215>                         }
 216 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l216>                       ungetc (c, fp);
 217 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l217>                       if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
 218 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l218>                         break;
 219 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l219>                       l1 = strlen (buf1);
 220 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l220>                       l2 = strlen (buf2);
 221 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l221>                       old_res_ptr = res_ptr;
 222 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l222>                       if (res_size == 0)
 223 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l223>                         {
 224 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l224>                           res_size = l1 + 1 + l2 + 1;
 225 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l225>                           res_ptr = (char *) malloc (res_size + 1);
 226 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l226>                         }
 227 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l227>                       else
 228 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l228>                         {
 229 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l229>                           res_size += l1 + 1 + l2 + 1;
 230 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l230>                           res_ptr = (char *) realloc (res_ptr, res_size + 1);
 231 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l231>                         }
 232 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l232>                       if (res_ptr == NULL)
 233 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l233>                         {
 234 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l234>                           /* Out of memory. */
 235 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l235>                           res_size = 0;
 236 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l236>                           free (old_res_ptr);
 237 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l237>                           break;
 238 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l238>                         }
 239 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l239>                       strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
 240 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l240>                       strcpy (res_ptr + res_size - (l2 + 1), buf2);
 241 <http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/localcharset.c;h=b4af28cd#l241>                     }