Reported by Thorsten Otto. Fixes #22.
case EXIF_TAG_XP_KEYWORDS:
case EXIF_TAG_XP_SUBJECT:
{
case EXIF_TAG_XP_KEYWORDS:
case EXIF_TAG_XP_SUBJECT:
{
/* Sanity check the size to prevent overflow */
/* Sanity check the size to prevent overflow */
- if (e->size+sizeof(unsigned short) < e->size) break;
+ if (e->size+sizeof(uint16_t)+1 < e->size) break;
/* The tag may not be U+0000-terminated , so make a local
U+0000-terminated copy before converting it */
/* The tag may not be U+0000-terminated , so make a local
U+0000-terminated copy before converting it */
- utf16 = exif_mem_alloc (e->priv->mem, e->size+sizeof(unsigned short));
+ utf16 = exif_mem_alloc (e->priv->mem, e->size+sizeof(uint16_t)+1);
if (!utf16) break;
memcpy(utf16, e->data, e->size);
/* NUL terminate the string. If the size is odd (which isn't possible
if (!utf16) break;
memcpy(utf16, e->data, e->size);
/* NUL terminate the string. If the size is odd (which isn't possible
- * for a UTF16 string), then this will overwrite the final garbage byte.
+ * for a valid UTF16 string), then this will overwrite the high byte of
+ * the final half word, plus add a full zero NUL word at the end.
- utf16[e->size/sizeof(unsigned short)] = 0;
+ utf16[e->size] = 0;
+ utf16[e->size+1] = 0;
+ utf16[e->size+2] = 0;
/* Warning! The texts are converted from UTF16 to UTF8 */
/* FIXME: use iconv to convert into the locale encoding */
/* Warning! The texts are converted from UTF16 to UTF8 */
/* FIXME: use iconv to convert into the locale encoding */
* It should really be replaced by iconv().
*/
void
* It should really be replaced by iconv().
*/
void
-exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen)
+exif_convert_utf16_to_utf8 (char *out, const unsigned char *in, int maxlen)
{
if (maxlen <= 0) {
return;
}
{
if (maxlen <= 0) {
return;
}
- while (*in) {
- if (*in < 0x80) {
+ for (;;) {
+ ExifShort v = exif_get_short(in, EXIF_BYTE_ORDER_INTEL);
+ if (!v)
+ break;
+ if (v < 0x80) {
maxlen--;
} else {
break;
}
maxlen--;
} else {
break;
}
- } else if (*in < 0x800) {
+ } else if (v < 0x800) {
- *out++ = ((*in >> 6) & 0x1F) | 0xC0;
- *out++ = (*in++ & 0x3F) | 0x80;
+ *out++ = ((v >> 6) & 0x1F) | 0xC0;
+ *out++ = (v & 0x3F) | 0x80;
maxlen -= 2;
} else {
break;
}
} else {
if (maxlen > 3) {
maxlen -= 2;
} else {
break;
}
} else {
if (maxlen > 3) {
- *out++ = ((*in >> 12) & 0x0F) | 0xE0;
- *out++ = ((*in >> 6) & 0x3F) | 0x80;
- *out++ = (*in++ & 0x3F) | 0x80;
+ *out++ = ((v >> 12) & 0x0F) | 0xE0;
+ *out++ = ((v >> 6) & 0x3F) | 0x80;
+ *out++ = (v & 0x3F) | 0x80;
maxlen -= 3;
} else {
break;
}
}
maxlen -= 3;
} else {
break;
}
}
ExifSRational value);
/*! \internal */
ExifSRational value);
/*! \internal */
-void exif_convert_utf16_to_utf8 (char *out, const unsigned short *in, int maxlen);
+void exif_convert_utf16_to_utf8 (char *out, const unsigned char *in, int maxlen);
/* Please do not use this function outside of the library. */
/* Please do not use this function outside of the library. */