Add a few more NULL pointer checks.
[platform/upstream/libexif.git] / libexif / exif-loader.c
index d5ec3c1..1171485 100644 (file)
@@ -1,13 +1,50 @@
+/* exif-loader.c
+ *
+ * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, 
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details. 
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301  USA.
+ */
+
 #include <config.h>
 
 #include <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
 #include <libexif/i18n.h>
 
+#include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 
-#include <libjpeg/jpeg-marker.h>
+#undef JPEG_MARKER_DHT
+#define JPEG_MARKER_DHT  0xc4
+#undef JPEG_MARKER_SOI
+#define JPEG_MARKER_SOI  0xd8
+#undef JPEG_MARKER_DQT
+#define JPEG_MARKER_DQT  0xdb
+#undef JPEG_MARKER_APP0
+#define JPEG_MARKER_APP0 0xe0
+#undef JPEG_MARKER_APP1
+#define JPEG_MARKER_APP1 0xe1
+#undef JPEG_MARKER_APP2
+#define JPEG_MARKER_APP2 0xe2
+#undef JPEG_MARKER_APP13
+#define JPEG_MARKER_APP13 0xed
+#undef JPEG_MARKER_COM
+#define JPEG_MARKER_COM 0xfe
 
 typedef enum {
        EL_READ = 0,
@@ -26,12 +63,15 @@ typedef enum {
        EL_DATA_FORMAT_FUJI_RAW
 } ExifLoaderDataFormat;
 
+/*! \internal */
 struct _ExifLoader {
        ExifLoaderState state;
        ExifLoaderDataFormat data_format;
 
-       /* Small buffer used for detection of format */
+       /*! Small buffer used for detection of format */
        unsigned char b[12];
+
+       /*! Number of bytes in the small buffer \c b */
        unsigned char b_len;
 
        unsigned int size;
@@ -44,6 +84,7 @@ struct _ExifLoader {
        ExifMem *mem;
 };
 
+/*! Magic number for EXIF header */
 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
 
 static void *
@@ -51,18 +92,17 @@ exif_loader_alloc (ExifLoader *l, unsigned int i)
 {
        void *d;
 
-       if (!l || !i) return NULL;
+       if (!l || !i) 
+               return NULL;
 
        d = exif_mem_alloc (l->mem, i);
-       if (d) return d;
+       if (d) 
+               return d;
 
        EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
        return NULL;
 }
 
-#undef  MIN
-#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
-
 void
 exif_loader_write_file (ExifLoader *l, const char *path)
 {
@@ -70,7 +110,8 @@ exif_loader_write_file (ExifLoader *l, const char *path)
        int size;
        unsigned char data[1024];
 
-       if (!l) return;
+       if (!l || !path)
+               return;
 
        f = fopen (path, "rb");
        if (!f) {
@@ -80,8 +121,10 @@ exif_loader_write_file (ExifLoader *l, const char *path)
        }
        while (1) {
                size = fread (data, 1, sizeof (data), f);
-               if (size <= 0) break;
-               if (!exif_loader_write (l, data, size)) break;
+               if (size <= 0) 
+                       break;
+               if (!exif_loader_write (l, data, size)) 
+                       break;
        }
        fclose (f);
 }
@@ -89,11 +132,14 @@ exif_loader_write_file (ExifLoader *l, const char *path)
 static unsigned int
 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
 {
-       if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) return 0;
+       if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) 
+               return 0;
 
        /* If needed, allocate the buffer. */
-       if (!eld->buf) eld->buf = exif_loader_alloc (eld, eld->size);
-       if (!eld->buf) return 0;
+       if (!eld->buf) 
+               eld->buf = exif_loader_alloc (eld, eld->size);
+       if (!eld->buf) 
+               return 0;
 
        /* Copy memory */
        len = MIN (len, eld->size - eld->bytes_read);
@@ -108,13 +154,17 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
 {
        unsigned int i;
 
-       if (!eld || (len && !buf)) return 0;
+       if (!eld || (len && !buf)) 
+               return 0;
 
        switch (eld->state) {
        case EL_EXIF_FOUND:
                return exif_loader_copy (eld, buf, len);
        case EL_SKIP_BYTES:
-               if (eld->size > len) { eld->size -= len; return 1; }
+               if (eld->size > len) { 
+                       eld->size -= len; 
+                       return 1; 
+               }
                len -= eld->size;
                buf += eld->size;
                eld->size = 0;
@@ -128,10 +178,14 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
                        break;
                }
                break;
+
+       case EL_READ:
        default:
                break;
        }
 
+       if (!len)
+               return 1;
        exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
                  "Scanning %i byte(s) of data...", len);
 
@@ -143,7 +197,8 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
        if (i) {
                memcpy (&eld->b[eld->b_len], buf, i);
                eld->b_len += i;
-               if (eld->b_len < sizeof (eld->b)) return 1;
+               if (eld->b_len < sizeof (eld->b)) 
+                       return 1;
                buf += i;
                len -= i;
        }
@@ -174,11 +229,13 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
                switch (eld->state) {
                case EL_EXIF_FOUND:
                        if (!exif_loader_copy (eld, eld->b + i,
-                                       sizeof (eld->b) - i)) return 0;
+                                       sizeof (eld->b) - i)) 
+                               return 0;
                        return exif_loader_copy (eld, buf, len);
                case EL_SKIP_BYTES:
                        eld->size--;
-                       if (!eld->size) eld->state = EL_READ;
+                       if (!eld->size) 
+                               eld->state = EL_READ;
                        break;
 
                case EL_READ_SIZE_BYTE_24:
@@ -216,11 +273,18 @@ exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
                default:
                        switch (eld->b[i]) {
                        case JPEG_MARKER_APP1:
-                               eld->data_format = EL_DATA_FORMAT_EXIF;
+                         if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
+                                       eld->data_format = EL_DATA_FORMAT_EXIF;
+                               } else {
+                                       eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
+                               }
                                eld->size = 0;
                                eld->state = EL_READ_SIZE_BYTE_08;
                                break;
+                       case JPEG_MARKER_DHT:
+                       case JPEG_MARKER_DQT:
                        case JPEG_MARKER_APP0:
+                       case JPEG_MARKER_APP2:
                        case JPEG_MARKER_APP13:
                        case JPEG_MARKER_COM:
                                eld->data_format = EL_DATA_FORMAT_JPEG;
@@ -265,10 +329,12 @@ exif_loader_new_mem (ExifMem *mem)
 {
        ExifLoader *loader;
 
-       if (!mem) return NULL;
+       if (!mem) 
+               return NULL;
        
        loader = exif_mem_alloc (mem, sizeof (ExifLoader));
-       if (!loader) return NULL;
+       if (!loader) 
+               return NULL;
        loader->ref_count = 1;
 
        loader->mem = mem;
@@ -280,7 +346,8 @@ exif_loader_new_mem (ExifMem *mem)
 void
 exif_loader_ref (ExifLoader *loader)
 {
-       if (loader) loader->ref_count++;
+       if (loader) 
+               loader->ref_count++;
 }
 
 static void
@@ -288,10 +355,12 @@ exif_loader_free (ExifLoader *loader)
 {
        ExifMem *mem;
 
-       if (!loader) return;
+       if (!loader) 
+               return;
 
        mem = loader->mem;
        exif_loader_reset (loader);
+       exif_log_unref (loader->log);
        exif_mem_free (mem, loader);
        exif_mem_unref (mem);
 }
@@ -299,7 +368,8 @@ exif_loader_free (ExifLoader *loader)
 void
 exif_loader_unref (ExifLoader *loader)
 {
-       if (!loader) return;
+       if (!loader) 
+               return;
        if (!--loader->ref_count)
                exif_loader_free (loader);
 }
@@ -307,7 +377,8 @@ exif_loader_unref (ExifLoader *loader)
 void
 exif_loader_reset (ExifLoader *loader)
 {
-       if (!loader) return;
+       if (!loader) 
+               return;
        exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
        loader->size = 0;
        loader->bytes_read = 0;
@@ -321,7 +392,9 @@ exif_loader_get_data (ExifLoader *loader)
 {
        ExifData *ed;
 
-       if (!loader) return NULL;
+       if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
+           !loader->bytes_read)
+               return NULL;
 
        ed = exif_data_new_mem (loader->mem);
        exif_data_log (ed, loader->log);
@@ -331,9 +404,33 @@ exif_loader_get_data (ExifLoader *loader)
 }
 
 void
+exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
+                                                 unsigned int *buf_size)
+{
+       const unsigned char* b = NULL;
+       unsigned int s = 0;
+
+       if (loader) {
+               if (loader->data_format == EL_DATA_FORMAT_UNKNOWN) {
+                       exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
+                                         "Loader format unknown");
+               } else {
+                       b = loader->buf;
+                       s = loader->bytes_read;
+               }
+       }
+
+       if (buf)
+               *buf = b;
+       if (buf_size)
+               *buf_size = s;
+}
+
+void
 exif_loader_log (ExifLoader *loader, ExifLog *log)
 {
-       if (!loader) return;
+       if (!loader) 
+               return;
        exif_log_unref (loader->log);
        loader->log = log;
        exif_log_ref (log);