Code Poetry
and Text Adventures

by catid posted (>30 days ago) 12:42pm Thu. Jan 2nd 2014 PST
I found that the Linaro version of libjpeg-turbo has a tjDecompress2() function that can write at least 1 byte beyond the end of the provided buffer.  This bug was causing hard to trace crashes in other parts of the code or right after image loading at 0xdeadbaad on Android.  It took me embarrassingly long to find this bug in our product.  Here's an example of the work-around:

   unsigned char *load_jpg_from_memory(unsigned char *bits, long bits_length, int *width, int *height, int *channels) {
     int jpegSubsamp, w, h, pitch;
     
     tjhandle _jpegDecompressor = tjInitDecompress();
     
     tjDecompressHeader2(_jpegDecompressor, bits, bits_length, &w, &h, &jpegSubsamp);
  
     pitch = tjPixelSize[TJPF_RGB] * w;
  
     unsigned char *buffer = malloc(pitch * h + 8);
     // Add 8 extra bytes to fix bug in tjDecompress where it is writing beyond the end of the buffer
  
     tjDecompress2(_jpegDecompressor, bits, bits_length, buffer, w, pitch, h, TJPF_RGB, TJFLAG_FASTDCT);
  
     tjDestroy(_jpegDecompressor);
  
     *width = w;
     *height = h;
     *channels = 3;
     return buffer;
   }

Verified this by scrubbing the input buffer and dumping the output buffer to see that it was writing a 0xff byte right after the supposed end of the buffer.  This was corrupting the malloc heap.

The crash was reproducibly found using this image: http://graph.facebook.com/100007136979512/picture?width=74&height=74.  Its unusual 74x74 pixel size is probably the culprit.

Bug reported on some Stack Overflow libjpeg-turbo posts for Android builds where people might find it in time.  It may affect other platforms.  Also reported to the developer of the library via Email.
last edit by catid edited (>30 days ago) 1:05pm Thu. Jan 2nd 2014 PST