From 1a29e47897a8e4d8da14ec408e520ff942755830 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Tue, 6 Nov 2018 00:53:56 +0100 Subject: [PATCH] Be a bit more robust in the face of out-of-memory errors. Do a better job in leaving things in a more consistent state after an allocation failure. Also, make the tests report and handle OOM conditions cleanly. --- libexif/exif-data.c | 5 +++++ libexif/exif-entry.c | 55 ++++++++++++++++++++++++++++------------------------ test/test-mem.c | 19 ++++++++++++++++++ test/test-mnote.c | 36 +++++++++++++++++++--------------- test/test-parse.c | 4 ++++ test/test-value.c | 42 +++++++++++++++++++-------------------- 6 files changed, 99 insertions(+), 62 deletions(-) diff --git a/libexif/exif-data.c b/libexif/exif-data.c index 350a887..e35403d 100644 --- a/libexif/exif-data.c +++ b/libexif/exif-data.c @@ -477,6 +477,11 @@ exif_data_load_data_content (ExifData *data, ExifIfd ifd, break; } entry = exif_entry_new_mem (data->priv->mem); + if (!entry) { + exif_log (data->priv->log, EXIF_LOG_CODE_NO_MEMORY, "ExifData", + "Could not allocate memory"); + return; + } if (exif_data_load_data_entry (data, entry, d, ds, offset + 12 * i)) exif_content_add_entry (data->ifd[ifd], entry); diff --git a/libexif/exif-entry.c b/libexif/exif-entry.c index b64f5d9..c0f219b 100644 --- a/libexif/exif-entry.c +++ b/libexif/exif-entry.c @@ -166,6 +166,13 @@ exif_entry_free (ExifEntry *e) } } +static void +clear_entry (ExifEntry *e) +{ + e->components = 0; + e->size = 0; +} + /*! Get a value and convert it to an ExifShort. * \bug Not all types are converted that could be converted and no indication * is made when that occurs @@ -367,8 +374,7 @@ exif_entry_fix (ExifEntry *e) if (e->size < 8) { e->data = exif_entry_realloc (e, e->data, 8 + e->size); if (!e->data) { - e->size = 0; - e->components = 0; + clear_entry(e); return; } @@ -410,8 +416,7 @@ exif_entry_fix (ExifEntry *e) memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)) { e->data = exif_entry_realloc (e, e->data, 8 + e->size); if (!e->data) { - e->size = 0; - e->components = 0; + clear_entry(e); break; } @@ -1419,7 +1424,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_LONG; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } break; /* SHORT, 1 component, no default */ @@ -1450,7 +1455,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 0); break; @@ -1462,7 +1467,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 1); break; @@ -1473,7 +1478,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 2); break; @@ -1483,7 +1488,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 3); break; @@ -1493,7 +1498,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 0xffff); break; @@ -1503,7 +1508,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 8); exif_set_short ( e->data + exif_format_get_size (e->format), @@ -1519,7 +1524,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SHORT; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } exif_set_short (e->data, o, 2); exif_set_short ( e->data + exif_format_get_size (e->format), @@ -1534,7 +1539,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_SRATIONAL; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } break; /* RATIONAL, 1 component, no default */ @@ -1555,7 +1560,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_RATIONAL; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } break; /* RATIONAL, 1 component, default 72/1 */ @@ -1565,7 +1570,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_RATIONAL; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } r.numerator = 72; r.denominator = 1; exif_set_rational (e->data, o, r); @@ -1577,7 +1582,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_RATIONAL; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } break; /* RATIONAL, 6 components */ @@ -1586,7 +1591,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_RATIONAL; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } r.denominator = 1; r.numerator = 0; exif_set_rational (e->data, o, r); @@ -1628,7 +1633,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_ASCII; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } snprintf ((char *) e->data, e->size, "%04i:%02i:%02i %02i:%02i:%02i", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, @@ -1656,7 +1661,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_ASCII; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } strncpy ((char *)e->data, _("[None]"), e->size); break; /* ASCII, default "[None]\0[None]\0" */ @@ -1665,7 +1670,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_ASCII; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } strcpy (((char *)e->data) + 0, _("[None]")); strcpy (((char *)e->data) + strlen (_("[None]")) + 1, _("[None]")); break; @@ -1676,7 +1681,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_UNDEFINED; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } e->data[0] = 0x01; break; @@ -1686,7 +1691,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_UNDEFINED; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } e->data[0] = 0x03; break; @@ -1696,7 +1701,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_UNDEFINED; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } memcpy (e->data, "0100", 4); break; @@ -1706,7 +1711,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_UNDEFINED; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } memcpy (e->data, "0210", 4); break; @@ -1716,7 +1721,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag) e->format = EXIF_FORMAT_UNDEFINED; e->size = exif_format_get_size (e->format) * e->components; e->data = exif_entry_alloc (e, e->size); - if (!e->data) break; + if (!e->data) { clear_entry(e); break; } e->data[0] = 1; e->data[1] = 2; e->data[2] = 3; diff --git a/test/test-mem.c b/test/test-mem.c index defcee9..e94df35 100644 --- a/test/test-mem.c +++ b/test/test-mem.c @@ -39,6 +39,11 @@ main () printf ("Creating EXIF data...\n"); ed = exif_data_new (); + if (!ed) { + fprintf(stderr, "Out of memory\n"); + exit(13); + } + exif_data_set_data_type (ed, EXIF_DATA_TYPE_UNCOMPRESSED_CHUNKY); printf ("Fill EXIF data with all necessary entries to follow specs...\n"); @@ -47,6 +52,11 @@ main () /* Add a dummy thumbnail */ ed->size = 4; ed->data = calloc(1, ed->size); + if (!ed->data) { + fprintf(stderr, "Out of memory\n"); + exif_data_unref (ed); + exit(13); + } exif_data_dump (ed); @@ -56,6 +66,11 @@ main () printf ("Writing %i byte(s) EXIF data to loader...\n", ebs); loader = exif_loader_new (); + if (!loader) { + fprintf(stderr, "Out of memory\n"); + free (eb); + exit(13); + } size[0] = (unsigned char) ebs; size[1] = (unsigned char) (ebs >> 8); exif_loader_write (loader, size, 2); @@ -63,6 +78,10 @@ main () printf ("Wrote %i byte(s).\n", i); free (eb); ed = exif_loader_get_data (loader); + if (!ed) { + fprintf(stderr, "Out of memory\n"); + exit(13); + } exif_loader_unref (loader); exif_data_dump (ed); exif_data_unref (ed); diff --git a/test/test-mnote.c b/test/test-mnote.c index 0c85a4f..81d452c 100644 --- a/test/test-mnote.c +++ b/test/test-mnote.c @@ -32,10 +32,10 @@ test_exif_data (ExifData *d) char v[1024], *p; ExifMnoteData *md; - fprintf (stdout, "Byte order: %s\n", + printf("Byte order: %s\n", exif_byte_order_get_name (exif_data_get_byte_order (d))); - fprintf (stdout, "Parsing maker note...\n"); + printf("Parsing maker note...\n"); md = exif_data_get_mnote_data (d); if (!md) { fprintf (stderr, "Could not parse maker note!\n"); @@ -43,25 +43,25 @@ test_exif_data (ExifData *d) return 1; } - fprintf (stdout, "Increasing ref-count...\n"); + printf("Increasing ref-count...\n"); exif_mnote_data_ref (md); - fprintf (stdout, "Decreasing ref-count...\n"); + printf("Decreasing ref-count...\n"); exif_mnote_data_unref (md); - fprintf (stdout, "Counting entries...\n"); + printf("Counting entries...\n"); c = exif_mnote_data_count (md); - fprintf (stdout, "Found %i entries.\n", c); + printf("Found %i entries.\n", c); for (i = 0; i < c; i++) { - fprintf (stdout, "Dumping entry number %i...\n", i); - fprintf (stdout, " Name: '%s'\n", + printf("Dumping entry number %i...\n", i); + printf(" Name: '%s'\n", exif_mnote_data_get_name (md, i)); - fprintf (stdout, " Title: '%s'\n", + printf(" Title: '%s'\n", exif_mnote_data_get_title (md, i)); - fprintf (stdout, " Description: '%s'\n", + printf(" Description: '%s'\n", exif_mnote_data_get_description (md, i)); p = exif_mnote_data_get_value (md, i, v, sizeof (v)); - if (p) { fprintf (stdout, " Value: '%s'\n", v); } + if (p) { printf(" Value: '%s'\n", v); } } return 0; @@ -80,28 +80,32 @@ main (int argc, char **argv) return 1; } - fprintf (stdout, "Loading '%s'...\n", argv[1]); + printf("Loading '%s'...\n", argv[1]); d = exif_data_new_from_file (argv[1]); if (!d) { fprintf (stderr, "Could not load data from '%s'!\n", argv[1]); return 1; } - fprintf (stdout, "Loaded '%s'.\n", argv[1]); + printf("Loaded '%s'.\n", argv[1]); - fprintf (stdout, "######### Test 1 #########\n"); + printf("######### Test 1 #########\n"); r = test_exif_data (d); if (r) return r; exif_data_save_data (d, &buf, &buf_size); exif_data_unref (d); d = exif_data_new_from_data (buf, buf_size); + if (!d) { + fprintf (stderr, "Could not load data from buf!\n"); + return 1; + } free (buf); - fprintf (stdout, "######### Test 2 #########\n"); + printf ("######### Test 2 #########\n"); r = test_exif_data (d); if (r) return r; - fprintf (stdout, "Test successful!\n"); + printf ("Test successful!\n"); return 1; } diff --git a/test/test-parse.c b/test/test-parse.c index c427c34..c32ab9c 100644 --- a/test/test-parse.c +++ b/test/test-parse.c @@ -92,6 +92,10 @@ static void test_parse(const char *filename, void *callback_data, int swap) printf("File %s\n", fn); d = exif_data_new_from_file(filename); + if (!d) { + fprintf (stderr, "Could not load data from '%s'!\n", filename); + return; + } printf("Byte order: %s\n", exif_byte_order_get_name(exif_data_get_byte_order(d))); diff --git a/test/test-value.c b/test/test-value.c index 557bb3a..860845e 100644 --- a/test/test-value.c +++ b/test/test-value.c @@ -131,7 +131,7 @@ main () data = exif_data_new (); if (!data) { - printf ("Error running exif_data_new()\n"); + fprintf (stderr, "Error running exif_data_new()\n"); exit(13); } @@ -139,7 +139,7 @@ main () for (i=0; i < sizeof(trunc_test_tags)/sizeof(trunc_test_tags[0]); ++i) { e = exif_entry_new (); if (!e) { - printf ("Error running exif_entry_new()\n"); + fprintf (stderr, "Error running exif_entry_new()\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -154,7 +154,7 @@ main () ++i) { e = exif_entry_new (); if (!e) { - printf ("Error running exif_entry_new()\n"); + fprintf (stderr, "Error running exif_entry_new()\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -169,7 +169,7 @@ main () ++i) { e = exif_entry_new (); if (!e) { - printf ("Error running exif_entry_new()\n"); + fprintf (stderr, "Error running exif_entry_new()\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -186,14 +186,14 @@ main () /* Create a memory allocator to manage the remaining ExifEntry structs */ mem = exif_mem_new_default(); if (!mem) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } /* EXIF_TAG_SUB_SEC_TIME initialization/truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -203,7 +203,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } memcpy(e->data, subsec, e->size); @@ -214,7 +214,7 @@ main () /* EXIF_TAG_USER_COMMENT initialization/truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -224,7 +224,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } memcpy(e->data, user_comment, e->size); @@ -235,7 +235,7 @@ main () /* EXIF_TAG_XP_COMMENT truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -246,7 +246,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } memcpy(e->data, xp_comment, e->size); @@ -257,7 +257,7 @@ main () /* EXIF_TAG_INTEROPERABILITY_VERSION truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_INTEROPERABILITY], e); @@ -269,7 +269,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } memcpy(e->data, interop, e->size); @@ -280,7 +280,7 @@ main () /* EXIF_TAG_GPS_VERSION_ID truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_GPS], e); @@ -291,7 +291,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } e->data[0] = 2; @@ -305,7 +305,7 @@ main () /* EXIF_TAG_GPS_ALTITUDE_REF truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_GPS], e); @@ -316,7 +316,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } e->data[0] = 1; @@ -327,7 +327,7 @@ main () /* EXIF_TAG_GPS_TIME_STAMP truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_GPS], e); @@ -338,7 +338,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_set_rational(e->data, exif_data_get_byte_order (data), gpsh); @@ -351,7 +351,7 @@ main () /* EXIF_TAG_SUBJECT_AREA truncation tests */ e = exif_entry_new_mem (mem); if (!e) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_content_add_entry (data->ifd[EXIF_IFD_0], e); @@ -364,7 +364,7 @@ main () /* Allocate memory to use for holding the tag data */ e->data = exif_mem_alloc(mem, e->size); if (!e->data) { - printf ("Out of memory\n"); + fprintf (stderr, "Out of memory\n"); exit(13); } exif_set_short(e->data, exif_data_get_byte_order (data), 123); -- 2.7.4