release-request-556939d2-cc5e-453a-b797-8a7cb6dacac2-for-git_nyc-mr1-security-f-release-4118426 snap-temp-L72200000081371809

Change-Id: Iefac5556fe41d42caa09a331e45e63e6cf2a5f3c
diff --git a/gdx/jni/com.badlogic.gdx.graphics.glutils.ETC1.cpp b/gdx/jni/com.badlogic.gdx.graphics.glutils.ETC1.cpp
index 94dc321..0c6eabd 100644
--- a/gdx/jni/com.badlogic.gdx.graphics.glutils.ETC1.cpp
+++ b/gdx/jni/com.badlogic.gdx.graphics.glutils.ETC1.cpp
@@ -1,4 +1,7 @@
 #include <com.badlogic.gdx.graphics.glutils.ETC1.h>
+#include <android/log.h>
+
+#define APP_LOG "GDX"
 
 //@line:196
 
@@ -86,9 +89,29 @@
 
 //@line:249
 

-		etc1_decode_image((etc1_byte*)compressedData + offset, (etc1_byte*)decodedData + offsetDec, width, height, pixelSize, width * pixelSize);

-	
+	// Nothing to decode, or no target
+	if (compressedData == 0 || decodedData == 0) {
+		__android_log_print(ANDROID_LOG_VERBOSE, APP_LOG, "Invalid buffers, null pointer.");
+		return;
+	}
 
+	/// Verify if requested bounds are valid
+	jlong compressedLength = env->GetDirectBufferCapacity(obj_compressedData);
+	jlong decodedLength = env->GetDirectBufferCapacity(obj_decodedData);
+	if (offset < 0 || compressedLength - offset > decodedLength - offsetDec) {
+		__android_log_print(ANDROID_LOG_VERBOSE,
+			APP_LOG, "Invalid buffers, would cause heap overflow. %lu > %lu",
+			compressedLength - offset,
+			decodedLength - offsetDec);
+		return;
+	}
+
+	etc1_decode_image((etc1_byte*)compressedData + offset,
+		(etc1_byte*)decodedData + offsetDec,
+		width,
+		height,
+		pixelSize,
+		width * pixelSize);
 }
 
 static inline jobject wrapped_Java_com_badlogic_gdx_graphics_glutils_ETC1_encodeImage
diff --git a/gdx/jni/gdx2d/gdx2d.c b/gdx/jni/gdx2d/gdx2d.c
index 13ceba2..70cfc7d 100644
--- a/gdx/jni/gdx2d/gdx2d.c
+++ b/gdx/jni/gdx2d/gdx2d.c
@@ -17,6 +17,9 @@
 #include "stb_image.h"

 #include "jpgd_c.h"

 

+#include <android/log.h>

+#define APP_LOG "GDX"

+

 static uint32_t gdx2d_blend = GDX2D_BLEND_NONE;

 static uint32_t gdx2d_scale = GDX2D_SCALE_NEAREST;

 

@@ -358,9 +361,25 @@
 	}

 }

 

-void gdx2d_clear(const gdx2d_pixmap* pixmap, uint32_t col) {	

+void gdx2d_clear(const gdx2d_pixmap* pixmap, uint32_t col) {

+	if (pixmap == 0)

+		return;

+

 	col = to_format(pixmap->format, col);

 

+	// Check for malformed Pixmap

+	size_t requestedSize = pixmap->width * pixmap->height * sizeof(col);

+	size_t pixelsSize = sizeof(pixmap->pixels);

+	if (requestedSize > pixelsSize) {

+		__android_log_print(ANDROID_LOG_VERBOSE,

+		APP_LOG, "Invalid pixmap. %ix%i - Size should be %u but found %u",

+		pixmap->width,

+		pixmap->height,

+		requestedSize,

+		pixelsSize);

+		return;

+	}

+

 	switch(pixmap->format) {

 		case GDX2D_FORMAT_ALPHA:

 			clear_alpha(pixmap, col);

diff --git a/gdx/jni/gdx2d/jpgd.cpp b/gdx/jni/gdx2d/jpgd.cpp
index 4c84a33..d76e930 100644
--- a/gdx/jni/gdx2d/jpgd.cpp
+++ b/gdx/jni/gdx2d/jpgd.cpp
@@ -29,6 +29,10 @@
 #define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b))
 #define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b))
 
+// TODO: Move to header and use these constants when declaring the arrays.
+#define JPGD_HUFF_TREE_MAX_LENGTH 512
+#define JPGD_HUFF_CODE_SIZE_MAX_LENGTH 256
+
 namespace jpgd {
 
 static inline void *jpgd_malloc(size_t nSize) { return malloc(nSize); }
@@ -493,8 +497,9 @@
 // Decodes a Huffman encoded symbol.
 inline int jpeg_decoder::huff_decode(huff_tables *pH)
 {
-  int symbol;
+  JPGD_ASSERT(pH);
 
+  int symbol;
   // Check first 8-bits: do we have a complete symbol?
   if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
   {
@@ -502,14 +507,19 @@
     int ofs = 23;
     do
     {
-      symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
+      unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
+      JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
+      symbol = pH->tree[idx];
       ofs--;
     } while (symbol < 0);
 
     get_bits_no_markers(8 + (23 - ofs));
   }
   else
+  {
+    JPGD_ASSERT(symbol < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
     get_bits_no_markers(pH->code_size[symbol]);
+  }
 
   return symbol;
 }
@@ -519,6 +529,8 @@
 {
   int symbol;
 
+  JPGD_ASSERT(pH);
+
   // Check first 8-bits: do we have a complete symbol?
   if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
   {
@@ -526,7 +538,9 @@
     int ofs = 23;
     do
     {
-      symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
+      unsigned int idx = -(int)(symbol + ((m_bit_buf >> ofs) & 1));
+      JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
+      symbol = pH->tree[idx];
       ofs--;
     } while (symbol < 0);
 
@@ -1497,6 +1511,12 @@
 void jpeg_decoder::transform_mcu(int mcu_row)
 {
   jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
+  if (m_freq_domain_chroma_upsample) {
+     JPGD_ASSERT(mcu_row * m_blocks_per_mcu < m_expanded_blocks_per_row);
+  }
+  else {
+     JPGD_ASSERT(mcu_row * m_blocks_per_mcu < m_max_blocks_per_row);
+  }
   uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
 
   for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
@@ -1652,6 +1672,7 @@
     for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
     {
       component_id = m_mcu_org[mcu_block];
+      JPGD_ASSERT(m_comp_quant[component_id] < JPGD_MAX_QUANT_TABLES);
       q = m_quant[m_comp_quant[component_id]];
 
       p = m_pMCU_coefficients + 64 * mcu_block;
@@ -1772,6 +1793,7 @@
     for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
     {
       int component_id = m_mcu_org[mcu_block];
+      JPGD_ASSERT(m_comp_quant[component_id] < JPGD_MAX_QUANT_TABLES);
       jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
 
       int r, s;
@@ -2281,7 +2303,8 @@
 
       for (l = 1 << (8 - code_size); l > 0; l--)
       {
-        JPGD_ASSERT(i < 256);
+        JPGD_ASSERT(i < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
+        JPGD_ASSERT(code < JPGD_HUFF_CODE_SIZE_MAX_LENGTH);
 
         pH->look_up[code] = i;
 
@@ -2331,16 +2354,19 @@
         if ((code & 0x8000) == 0)
           currententry--;
 
-        if (pH->tree[-currententry - 1] == 0)
+        unsigned int idx = -currententry - 1;
+        JPGD_ASSERT(idx < JPGD_HUFF_TREE_MAX_LENGTH);
+        if (pH->tree[idx] == 0)
         {
-          pH->tree[-currententry - 1] = nextfreeentry;
+          pH->tree[idx] = nextfreeentry;
 
           currententry = nextfreeentry;
 
           nextfreeentry -= 2;
         }
-        else
-          currententry = pH->tree[-currententry - 1];
+        else {
+          currententry = pH->tree[idx];
+        }
 
         code <<= 1;
       }
@@ -2642,7 +2668,9 @@
 
   for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
   {
-    s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
+    unsigned int idx = pD->m_comp_ac_tab[component_id];
+    JPGD_ASSERT(idx < JPGD_MAX_HUFF_TABLES);
+    s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
 
     r = s >> 4;
     s &= 15;
@@ -2685,7 +2713,6 @@
   int p1 = 1 << pD->m_successive_low;
   int m1 = (-1) << pD->m_successive_low;
   jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
-  
   JPGD_ASSERT(pD->m_spectral_end <= 63);
   
   k = pD->m_spectral_start;
@@ -2694,7 +2721,9 @@
   {
     for ( ; k <= pD->m_spectral_end; k++)
     {
-      s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
+      unsigned int idx = pD->m_comp_ac_tab[component_id];
+      JPGD_ASSERT(idx < JPGD_MAX_HUFF_TABLES);
+      s = pD->huff_decode(pD->m_pHuff_tabs[idx]);
 
       r = s >> 4;
       s &= 15;
diff --git a/gdx/jni/gdx2d/stb_image.h b/gdx/jni/gdx2d/stb_image.h
index a9d338a..1e48cc4 100644
--- a/gdx/jni/gdx2d/stb_image.h
+++ b/gdx/jni/gdx2d/stb_image.h
@@ -965,6 +965,9 @@
    #ifndef STBI_NO_HDR
    if (stbi__hdr_test(s)) {
       float *hdr = stbi__hdr_load(s, x,y,comp,req_comp);
+      if (hdr == NULL) {
+         return NULL;
+      }
       return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
    }
    #endif
@@ -6046,7 +6049,11 @@
          }
          len <<= 8;
          len |= stbi__get8(s);
-         if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); }
+         if (len != width) {
+            STBI_FREE(hdr_data);
+            STBI_FREE(scanline);
+            return stbi__errpf("invalid decoded scanline length", "corrupt HDR");
+         }
          if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4);
 
          for (k = 0; k < 4; ++k) {
@@ -6057,9 +6064,19 @@
                   // Run
                   value = stbi__get8(s);
                   count -= 128;
+                  if (count >= width - i) {
+                     STBI_FREE(hdr_data);
+                     STBI_FREE(scanline);
+                     return stbi__errpf("invalid buffer size", "corrupt HDR");
+                  }
                   for (z = 0; z < count; ++z)
                      scanline[i++ * 4 + k] = value;
                } else {
+                  if (count >= width - i) {
+                     STBI_FREE(hdr_data);
+                     STBI_FREE(scanline);
+                     return stbi__errpf("invalid buffer size", "corrupt HDR");
+                  }
                   // Dump
                   for (z = 0; z < count; ++z)
                      scanline[i++ * 4 + k] = stbi__get8(s);