Skip to content

Commit 4f9a112

Browse files
committed
Avoid out of range float to int cast in exif
Use convert_any_int instead of convert_any_format to directly get an integer. Also adjust SRATIONAL handling to not go through a double division. This was introduced to avoid SIGFPE for the INT_MIN / -1 case, but we can just handle that explicitly.
1 parent bf4f3dd commit 4f9a112

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

ext/exif/exif.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,31 +1710,33 @@ static size_t double_to_size_t(double x) {
17101710
* Evaluate number, be it int, rational, or float from directory. */
17111711
static size_t exif_convert_any_to_int(void *value, int format, int motorola_intel)
17121712
{
1713-
int s_den;
1714-
unsigned u_den;
1715-
1716-
switch(format) {
1713+
switch (format) {
17171714
case TAG_FMT_SBYTE: return *(signed char *)value;
17181715
case TAG_FMT_BYTE: return *(uchar *)value;
17191716

17201717
case TAG_FMT_USHORT: return php_ifd_get16u(value, motorola_intel);
17211718
case TAG_FMT_ULONG: return php_ifd_get32u(value, motorola_intel);
17221719

1723-
case TAG_FMT_URATIONAL:
1724-
u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
1720+
case TAG_FMT_URATIONAL: {
1721+
unsigned u_den = php_ifd_get32u(4+(char *)value, motorola_intel);
17251722
if (u_den == 0) {
17261723
return 0;
17271724
} else {
17281725
return php_ifd_get32u(value, motorola_intel) / u_den;
17291726
}
1727+
}
17301728

1731-
case TAG_FMT_SRATIONAL:
1732-
s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
1729+
case TAG_FMT_SRATIONAL: {
1730+
int s_num = php_ifd_get32s(value, motorola_intel);
1731+
int s_den = php_ifd_get32s(4+(char *)value, motorola_intel);
17331732
if (s_den == 0) {
17341733
return 0;
1734+
} else if (s_num == INT_MIN && s_den == -1) {
1735+
return INT_MAX;
17351736
} else {
1736-
return (size_t)((double)php_ifd_get32s(value, motorola_intel) / s_den);
1737+
return s_num / s_den;
17371738
}
1739+
}
17381740

17391741
case TAG_FMT_SSHORT: return php_ifd_get16u(value, motorola_intel);
17401742
case TAG_FMT_SLONG: return php_ifd_get32s(value, motorola_intel);
@@ -3473,7 +3475,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, con
34733475

34743476
case TAG_FOCALPLANE_RESOLUTION_UNIT:
34753477
REQUIRE_NON_EMPTY();
3476-
switch((int)exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel)) {
3478+
switch (exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel)) {
34773479
case 1: ImageInfo->FocalplaneUnits = 25.4; break; /* inch */
34783480
case 2:
34793481
/* According to the information I was using, 2 measn meters.

0 commit comments

Comments
 (0)