Control: tags -1 + patch

On 2013-02-05 11:01:39, Sang Kil Cha wrote:
> imview has stack smashing vulnerability when parsing ics header @
> io/readics.cxx:320
> 
>      /* get the filename from the ICS file */
> 
>          t = temp1;
>              while (*bp != delim2)
>                      *t++ = *bp++;

The attached patch should fix this bug. It adds bounds checking for all
the parts that read in a way like that.

The provided file doesn't crash with the patch, but since I don't have
any ICS images, someone else should check if the patch doesn't break
anything.

Regards
-- 
Sebastian Ramacher
--- a/io/readics.cxx
+++ b/io/readics.cxx
@@ -273,6 +273,13 @@
     /* get the length of the ICS file and rewind */
     length = (unsigned int)lseek(fd,0L,2);
     lseek(fd,0L,0);
+
+    /* the first two characters are the seperators */
+    if (length < 2)
+    {
+      close(fd);
+      return -4;
+    }
    
   /* allocate space for all data from the ICS file */
     if ((buffer1 = (char *)malloc(length)) == NULL)
@@ -321,10 +328,15 @@
     delim1 = *bp++;	/* field delimiter */
     delim2 = *bp++;	/* record delimiter */
     t = temp1;
- 
+
+    size_t bread = 0;
+
     /* check if written by ICS */
-    while (*bp != delim2)
-	*t++ = *bp++;
+    while (*bp != delim2 && bread < 3 && bp != end)
+    {
+    	*t++ = *bp++;
+      ++bread;
+    }
     bp++;
     *t = '\0';
     if (strncmp(temp1,"ICS",3) && strncmp(temp1,"ics",3))
@@ -337,13 +349,18 @@
     /* get the filename from the ICS file */
 
     t = temp1;
-    while (*bp != delim2)
-	*t++ = *bp++;
+    bread = 0;
+    while (*bp != delim2 && bread < sizeof(temp1) - 1 && bp != end)
+    {
+    	*t++ = *bp++;
+      ++bread;
+    }
     bp++;
     *t = '\0';
 
     t = strchr(temp1,delim1);
-    strcpy(icsheader->filename,t);
+    strncpy(icsheader->filename,t, FILENAME_SIZE);
+    icsheader->filename[FILENAME_SIZE - 1] = '\0';
     *t = '\0';
 
     if (strcmp(temp1,"filename"))
@@ -360,18 +377,27 @@
     {
 	/* get the next record into temp1 */
 	t = temp1;
-	while (*bp != delim2 && bp < end)	/* dont read beyond EOF */
-	    *t++ = *bp++;
+  bread = 0;
+	while (*bp != delim2 && bp < end && bread < sizeof(temp1) - 1)	/* dont read beyond EOF */
+  {
+    *t++ = *bp++;
+    ++bread;
+  }
 	bp++;
 	*t = '\0';
       
       /* get the category into temp2 */
+  bread = 0;
 	t = temp1;
 	tg = temp2;
-	while (*t != delim1)
+	while (*t != delim1 && bread < sizeof(temp1) - 1)
+  {
 	    *tg++ = *t++;
+      ++bread;
+  }
 	t++;
 	*tg = '\0';
+  ++bread;
 
       /* check if it is one of the decodable categories */
 	cat = 0;
@@ -388,10 +414,14 @@
 	}
 	/* get the next field from this record */
 	tg = temp2;
-	while (*t != delim1)
+	while (*t != delim1 && bread < sizeof(temp1) - 1)
+  {
 	    *tg++ = *t++;
+      ++bread;
+  }
 	t++;
 	*tg = '\0';
+  ++bread;
 
       /* find this item in the keyword table */
 	for (i = 0; i < kwrds; i++)
@@ -415,10 +445,14 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+        *tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
+      ++bread;
 	    icsheader->parameters = atoi(temp2);
 	    if (icsheader->parameters > MAXDIM)
 	    {  /* if necessary change MAXDIM in ics.h */
@@ -444,11 +478,15 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
-		strcpy(icsheader->order[i],temp2);
+		strncpy(icsheader->order[i],temp2, ORDER_SIZE);
+    icsheader->order[i][ORDER_SIZE - 1] = '\0';
 	    }
 	    icsheader->valid_order = TRUE;
 	    break;
@@ -468,10 +506,14 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
+    ++bread;
 		icsheader->sizes[i] = atoi(temp2);
 	    }
 	    icsheader->valid_sizes = TRUE;
@@ -484,11 +526,16 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
-	    strcpy(icsheader->coord,temp2);
+      ++bread;
+	    strncpy(icsheader->coord,temp2, COORD_SIZE);
+      icsheader->coord[COORD_SIZE - 1] = '\0';
 	    icsheader->valid_coord = TRUE;
 	    break;
 	  case 4: /* significant bits */
@@ -499,10 +546,14 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
+      ++bread;
 	    icsheader->sigbits = atoi(temp2);
 	    icsheader->valid_sigbits = TRUE;
 	    break;
@@ -514,11 +565,16 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
-	    strcpy(icsheader->format,temp2);
+      ++bread;
+	    strncpy(icsheader->format,temp2, FORMAT_SIZE);
+      icsheader->format[FORMAT_SIZE - 1] = '\0';
 	    icsheader->valid_format = TRUE;
 	    break;
 	  case 6: /* signed or unsigned */
@@ -529,10 +585,14 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
+      ++bread;
 	    if (!strcmp(temp2,"unsigned"))
 		icsheader->sign = UNSIGNED;
 	    else icsheader->sign = SIGNED;
@@ -546,11 +606,16 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
-	    strcpy(icsheader->compression,temp2);
+      ++bread;
+	    strncpy(icsheader->compression,temp2, CMPS_SIZE);
+      icsheader->compression[CMPS_SIZE - 1] = '\0';
 	    icsheader->valid_compression = TRUE;
 	    break;
 	  case 8: /* origin */
@@ -569,10 +634,14 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
+    ++bread;
 		icsheader->origin[i] = (float)atof(temp2);
 	    }
 	    icsheader->valid_origin = TRUE;
@@ -593,10 +662,14 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
+    ++bread;
 		icsheader->scale[i] = (float)atof(temp2);
 	    }
 	    icsheader->valid_scale = TRUE;
@@ -617,11 +690,16 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
-		strcpy(icsheader->label[i],temp2);
+    ++bread;
+		strncpy(icsheader->label[i],temp2, LABEL_SIZE);
+    icsheader->label[i][LABEL_SIZE - 1] = '\0';
 	    }
 	    icsheader->valid_label = TRUE;
 	    break;
@@ -641,11 +719,16 @@
 	    for (i = 0; i < icsheader->parameters; i++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
-		strcpy(icsheader->units[i],temp2);
+    ++bread;
+		strncpy(icsheader->units[i],temp2, UNITS_SIZE);
+    icsheader->units[i][UNITS_SIZE - 1] = '\0';
 	    }
 	    icsheader->valid_units = TRUE;
 	    break;
@@ -666,10 +749,14 @@
 	    for (ui = 0; ui < length; ui++)
 	    {
 		tg = temp2;
-		while (*t != delim1 && *t != '\0')
+		while (*t != delim1 && *t != '\0' && bread < sizeof(temp1) - 1)
+    {
 		    *tg++ = *t++;
+        ++bread;
+    }
 		*tg = '\0';
 		t++;
+    ++bread;
 		icsheader->byteorder[ui] = atoi(temp2);
 	    }
 	    icsheader->valid_byteorder = TRUE;
@@ -682,11 +769,16 @@
 		break;
 	    }
 	    tg = temp2;
-	    while (*t != '\0')
-		*tg++ = *t++;
+	    while (*t != '\0' && bread < sizeof(temp1) - 1)
+      {
+    		*tg++ = *t++;
+        ++bread;
+      }
 	    *tg = '\0';
 	    t++;
-	    strcpy(icsheader->SCIL_TYPE,temp2);
+      ++bread;
+	    strncpy(icsheader->SCIL_TYPE,temp2, SCIL_SIZE);
+      icsheader->SCIL_TYPE[SCIL_SIZE - 1] = '\0';
 	    icsheader->valid_SCIL_TYPE = TRUE;
 	    break;
 	  default:

Attachment: signature.asc
Description: Digital signature

Reply via email to