CVE-2017-16910: Out-of-bounds Read (CWE-125)
value: An error within the "LibRaw::xtrans_interpolate()" function (internal/dcraw_common.cpp) in LibRaw versions prior to 0.18.6 can be exploited to cause an invalid read memory access and subsequently a Denial of Service condition.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 6.5
Published: 2018-12-07T22:29Z
Repository: https://github.com/LibRaw/LibRaw
Language: C++
Files changed: dcraw/dcraw.c, internal/dcraw_common.cpp
Commit date: 2017-12-02 12:28:37 +0300
Commit message: Secunia 76000 #2: xtrans allhex not initialized

Diff: diff --git a/dcraw/dcraw.c b/dcraw/dcraw.c
index 7ce50e65..54c954a1 100644
--- a/dcraw/dcraw.c
+++ b/dcraw/dcraw.c
@@ -7043,28 +7043,38 @@ void CLASS xtrans_interpolate(int passes)
   if (verbose)
     fprintf(stderr, _("%d-pass X-Trans interpolation...\n"), passes);
 #endif
 
 #ifdef LIBRAW_LIBRARY_BUILD
+  if(width < TS || height < TS)
+	  throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image
 /* Check against right pattern */
   for (row = 0; row < 6; row++)
 	  for (col = 0; col < 6; col++)
 		  cstat[fcol(row,col)]++;
 
   if(cstat[0] < 6 || cstat[0]>10 || cstat[1]< 16
     || cstat[1]>24 || cstat[2]< 6 || cstat[2]>10 || cstat[3])
 	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ // Init allhex table to unreasonable values
+ for(int i = 0; i < 3; i++)
+  for(int j = 0; j < 3; j++)
+   for(int k = 0; k < 2; k++)
+    for(int l = 0; l < 8; l++)
+     allhex[i][j][k][l]=32700;
 #endif
   cielab(0, 0);
   ndir = 4 << (passes > 1);
   buffer = (char *)malloc(TS * TS * (ndir * 11 + 6));
   merror(buffer, "xtrans_interpolate()");
   rgb = (ushort(*)[TS][TS][3])buffer;
   lab = (short(*)[TS][3])(buffer + TS * TS * (ndir * 6));
   drv = (float(*)[TS][TS])(buffer + TS * TS * (ndir * 6 + 6));
   homo = (char(*)[TS][TS])(buffer + TS * TS * (ndir * 10 + 6));
 
+  int minv=0,maxv=0,minh=0,maxh=0;
   /* Map a green hexagon around each non-green pixel and vice versa:	*/
   for (row = 0; row < 3; row++)
     for (col = 0; col < 3; col++)
       for (ng = d = 0; d < 10; d += 2)
       {
@@ -7081,15 +7091,29 @@ void CLASS xtrans_interpolate(int passes)
         if (ng == g + 1)
           FORC(8)
           {
             v = orth[d] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1];
             h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1];
+	    minv=MIN(v,minv);
+	    maxv=MAX(v,maxv);
+	    minh=MIN(v,minh);
+   	    maxh=MAX(v,maxh);
             allhex[row][col][0][c ^ (g * 2 & d)] = h + v * width;
             allhex[row][col][1][c ^ (g * 2 & d)] = h + v * TS;
           }
       }
 
+#ifdef LIBRAW_LIBRARY_BUILD
+   // Check allhex table initialization
+  for(int i = 0; i < 3; i++)
+    for(int j = 0; j < 3; j++)
+      for(int k = 0; k < 2; k++)
+        for(int l = 0; l < 8; l++)
+	  if(allhex[i][j][k][l]>maxh+maxv*width+1 || allhex[i][j][k][l]<minh+minv*width-1)
+	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
+  int retrycount = 0;
+#endif
   /* Set green1 and green3 to the minimum and maximum allowed values:	*/
   for (row = 2; row < height - 2; row++)
     for (min = ~(max = 0), col = 2; col < width - 2; col++)
     {
       if (fcol(row, col) == 1 && (min = ~(max = 0)))
@@ -7116,11 +7140,17 @@ void CLASS xtrans_interpolate(int passes)
           col--;
         }
         break;
       case 2:
         if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2)
-          row--;
+	{
+           row--;
+#ifdef LIBRAW_LIBRARY_BUILD
+	  if(retrycount++ > width*height)
+	  	throw LIBRAW_EXCEPTION_IO_CORRUPT;
+#endif
+	}
       }
     }
 
   for (top = 3; top < height - 19; top += TS - 16)
     for (left = 3; left < width - 19; left += TS - 16)
diff --git a/internal/dcraw_common.cpp b/internal/dcraw_common.cpp
index 56f37a30..e0fe6f40 100644
--- a/internal/dcraw_common.cpp
+++ b/internal/dcraw_common.cpp
@@ -5725,28 +5725,38 @@ void CLASS xtrans_interpolate(int passes)
   if (verbose)
     fprintf(stderr, _("%d-pass X-Trans interpolation...\n"), passes);
 #endif
 
 #ifdef LIBRAW_LIBRARY_BUILD
+  if(width < TS || height < TS)
+	  throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image
 /* Check against right pattern */
   for (row = 0; row < 6; row++)
 	  for (col = 0; col < 6; col++)
 		  cstat[fcol(row,col)]++;
 
   if(cstat[0] < 6 || cstat[0]>10 || cstat[1]< 16
     || cstat[1]>24 || cstat[2]< 6 || cstat[2]>10 || cstat[3])
 	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
+
+ // Init allhex table to unreasonable values
+ for(int i = 0; i < 3; i++)
+  for(int j = 0; j < 3; j++)
+   for(int k = 0; k < 2; k++)
+    for(int l = 0; l < 8; l++)
+     allhex[i][j][k][l]=32700;
 #endif
   cielab(0, 0);
   ndir = 4 << (passes > 1);
   buffer = (char *)malloc(TS * TS * (ndir * 11 + 6));
   merror(buffer, "xtrans_interpolate()");
   rgb = (ushort(*)[TS][TS][3])buffer;
   lab = (short(*)[TS][3])(buffer + TS * TS * (ndir * 6));
   drv = (float(*)[TS][TS])(buffer + TS * TS * (ndir * 6 + 6));
   homo = (char(*)[TS][TS])(buffer + TS * TS * (ndir * 10 + 6));
 
+  int minv=0,maxv=0,minh=0,maxh=0;
   /* Map a green hexagon around each non-green pixel and vice versa:	*/
   for (row = 0; row < 3; row++)
     for (col = 0; col < 3; col++)
       for (ng = d = 0; d < 10; d += 2)
       {
@@ -5763,15 +5773,29 @@ void CLASS xtrans_interpolate(int passes)
         if (ng == g + 1)
           FORC(8)
           {
             v = orth[d] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1];
             h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1];
+	    minv=MIN(v,minv);
+	    maxv=MAX(v,maxv);
+	    minh=MIN(v,minh);
+   	    maxh=MAX(v,maxh);
             allhex[row][col][0][c ^ (g * 2 & d)] = h + v * width;
             allhex[row][col][1][c ^ (g * 2 & d)] = h + v * TS;
           }
       }
 
+#ifdef LIBRAW_LIBRARY_BUILD
+   // Check allhex table initialization
+  for(int i = 0; i < 3; i++)
+    for(int j = 0; j < 3; j++)
+      for(int k = 0; k < 2; k++)
+        for(int l = 0; l < 8; l++)
+	  if(allhex[i][j][k][l]>maxh+maxv*width+1 || allhex[i][j][k][l]<minh+minv*width-1)
+	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
+  int retrycount = 0;
+#endif
   /* Set green1 and green3 to the minimum and maximum allowed values:	*/
   for (row = 2; row < height - 2; row++)
     for (min = ~(max = 0), col = 2; col < width - 2; col++)
     {
       if (fcol(row, col) == 1 && (min = ~(max = 0)))
@@ -5798,11 +5822,17 @@ void CLASS xtrans_interpolate(int passes)
           col--;
         }
         break;
       case 2:
         if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2)
-          row--;
+	{
+           row--;
+#ifdef LIBRAW_LIBRARY_BUILD
+	  if(retrycount++ > width*height)
+	  	throw LIBRAW_EXCEPTION_IO_CORRUPT;
+#endif
+	}
       }
     }
 
   for (top = 3; top < height - 19; top += TS - 16)
     for (left = 3; left < width - 19; left += TS - 16)

Vulnerable code:           row--;
          row--;
Fixed code:   if(width < TS || height < TS)
	  throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image

 // Init allhex table to unreasonable values
 for(int i = 0; i < 3; i++)
  for(int j = 0; j < 3; j++)
   for(int k = 0; k < 2; k++)
    for(int l = 0; l < 8; l++)
     allhex[i][j][k][l]=32700;
  int minv=0,maxv=0,minh=0,maxh=0;
	    minv=MIN(v,minv);
	    maxv=MAX(v,maxv);
	    minh=MIN(v,minh);
   	    maxh=MAX(v,maxh);
#ifdef LIBRAW_LIBRARY_BUILD
   // Check allhex table initialization
  for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
      for(int k = 0; k < 2; k++)
        for(int l = 0; l < 8; l++)
	  if(allhex[i][j][k][l]>maxh+maxv*width+1 || allhex[i][j][k][l]<minh+minv*width-1)
	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
  int retrycount = 0;
#endif
	{
           row--;
#ifdef LIBRAW_LIBRARY_BUILD
	  if(retrycount++ > width*height)
	  	throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
	}
  if(width < TS || height < TS)
	  throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image

 // Init allhex table to unreasonable values
 for(int i = 0; i < 3; i++)
  for(int j = 0; j < 3; j++)
   for(int k = 0; k < 2; k++)
    for(int l = 0; l < 8; l++)
     allhex[i][j][k][l]=32700;
  int minv=0,maxv=0,minh=0,maxh=0;
	    minv=MIN(v,minv);
	    maxv=MAX(v,maxv);
	    minh=MIN(v,minh);
   	    maxh=MAX(v,maxh);
#ifdef LIBRAW_LIBRARY_BUILD
   // Check allhex table initialization
  for(int i = 0; i < 3; i++)
    for(int j = 0; j < 3; j++)
      for(int k = 0; k < 2; k++)
        for(int l = 0; l < 8; l++)
	  if(allhex[i][j][k][l]>maxh+maxv*width+1 || allhex[i][j][k][l]<minh+minv*width-1)
	  throw LIBRAW_EXCEPTION_IO_CORRUPT;
  int retrycount = 0;
#endif
	{
           row--;
#ifdef LIBRAW_LIBRARY_BUILD
	  if(retrycount++ > width*height)
	  	throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
	}