[PATCH]: Fix SIGBUS in JPEG handling on RISC
- From: David Miller <davem davemloft net>
- To: gtk-devel-list gnome org
- Cc: timj gtk org, mclasen redhat com
- Subject: [PATCH]: Fix SIGBUS in JPEG handling on RISC
- Date: Thu, 01 Nov 2007 03:04:21 -0700 (PDT)
Several RISC cpus cannot access data which is not aligned
properly for it's type.
The JPEG orientation handling dereferences potentially unaligned
values. It also improperly casts the 32-bit ones, using "unsigned
long" which is typically 64-bit on 64-bit platforms.
This patch corrects both errors, curing the SIGBUS issues on
my sparc systems.
gthumb has the same exact buggy EXIF parsing code, and I'm about to
send a similar patch to that module's maintainer too.
Please apply, thanks.
2007-11-01 David S. Miller <davem davemloft net>
* gdk-pixbuf/io-jpeg.c (de_get16, de_get32): New functions.
(get_orientation): Use them to avoid unaligned accesses and
access 32-bit values correctly on 64-bit platforms.
Index: gdk-pixbuf/io-jpeg.c
===================================================================
--- gdk-pixbuf/io-jpeg.c (revision 18959)
+++ gdk-pixbuf/io-jpeg.c (working copy)
@@ -292,6 +292,26 @@ const char types[] = {0x00, 0x01, 0x01,
#define EXIF_JPEG_MARKER JPEG_APP0+1
#define EXIF_IDENT_STRING "Exif\000\000"
+static unsigned short de_get16(void *ptr, guint endian)
+{
+ unsigned short val;
+
+ memcpy(&val, ptr, sizeof(val));
+ val = DE_ENDIAN16(val);
+
+ return val;
+}
+
+static unsigned int de_get32(void *ptr, guint endian)
+{
+ unsigned int val;
+
+ memcpy(&val, ptr, sizeof(val));
+ val = DE_ENDIAN32(val);
+
+ return val;
+}
+
static gint
get_orientation (j_decompress_ptr cinfo)
{
@@ -382,7 +402,7 @@ get_orientation (j_decompress_ptr cinfo)
orient_tag_id = ENDIAN16_IT(0x112);
/* Read out the offset pointer to IFD0 */
- offset = DE_ENDIAN32(*((unsigned long*) (&exif_marker->data[i] + 4)));
+ offset = de_get32(&exif_marker->data[i] + 4, endian);
i = i + offset;
/* Check that we still are within the buffer and can read the tag count */
@@ -391,7 +411,7 @@ get_orientation (j_decompress_ptr cinfo)
/* Find out how many tags we have in IFD0. As per the TIFF spec, the first
two bytes of the IFD contain a count of the number of tags. */
- tags = DE_ENDIAN16(*((unsigned short*) (&exif_marker->data[i])));
+ tags = de_get16(&exif_marker->data[i], endian);
i = i + 2;
/* Check that we still have enough data for all tags to check. The tags
@@ -402,8 +422,8 @@ get_orientation (j_decompress_ptr cinfo)
/* Check through IFD0 for tags of interest */
while (tags--){
- type = DE_ENDIAN16(*((unsigned short*)(&exif_marker->data[i + 2])));
- count = DE_ENDIAN32(*((unsigned long*) (&exif_marker->data[i + 4])));
+ type = de_get16(&exif_marker->data[i + 2], endian);
+ count = de_get32(&exif_marker->data[i + 4], endian);
/* Is this the orientation tag? */
if (memcmp (&exif_marker->data[i], (char *) &orient_tag_id, 2) == 0){
@@ -414,7 +434,7 @@ get_orientation (j_decompress_ptr cinfo)
/* Return the orientation value. Within the 12-byte block, the
pointer to the actual data is at offset 8. */
- ret = DE_ENDIAN16(*((unsigned short*) (&exif_marker->data[i + 8])));
+ ret = de_get16(&exif_marker->data[i + 8], endian);
return ret <= 8 ? ret : 0;
}
/* move the pointer to the next 12-byte tag field. */
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]