Skip to content

Commit 551a9ef

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-16559: UBSan abort in ext/gd/libgd/gd_interpolation.c:1007
2 parents 5fc238f + d7e7e2b commit 551a9ef

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

ext/gd/libgd/gd_interpolation.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -919,21 +919,29 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
919919
return res;
920920
}
921921

922+
/* Convert a double to an unsigned char, rounding to the nearest
923+
* integer and clamping the result between 0 and max. The absolute
924+
* value of clr must be less than the maximum value of an unsigned
925+
* short. */
922926
static inline unsigned char
923-
uchar_clamp(double clr) {
927+
uchar_clamp(double clr, unsigned char max) {
924928
unsigned short result;
925-
assert(fabs(clr) <= SHRT_MAX);
929+
930+
//assert(fabs(clr) <= SHRT_MAX);
931+
926932
/* Casting a negative float to an unsigned short is undefined.
927933
* However, casting a float to a signed truncates toward zero and
928934
* casting a negative signed value to an unsigned of the same size
929935
* results in a bit-identical value (assuming twos-complement
930936
* arithmetic). This is what we want: all legal negative values
931937
* for clr will be greater than 255. */
938+
932939
/* Convert and clamp. */
933940
result = (unsigned short)(short)(clr + 0.5);
934-
if (result > 255) {
935-
result = (clr < 0) ? 0 : 255;
941+
if (result > max) {
942+
result = (clr < 0) ? 0 : max;
936943
}/* if */
944+
937945
return result;
938946
}/* uchar_clamp*/
939947

@@ -957,7 +965,9 @@ static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImage
957965
b += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i]));
958966
a += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i]));
959967
}
960-
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
968+
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF),
969+
uchar_clamp(b, 0xFF),
970+
uchar_clamp(a, 0x7F)); /* alpha is 0..127 */
961971
}
962972
}
963973

@@ -1004,7 +1014,9 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
10041014
b += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc));
10051015
a += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc));
10061016
}
1007-
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
1017+
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF),
1018+
uchar_clamp(b, 0xFF),
1019+
uchar_clamp(a, 0x7F)); /* alpha is 0..127 */
10081020
}
10091021
}
10101022

ext/gd/tests/gh16559.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007)
3+
--EXTENSIONS--
4+
gd
5+
--FILE--
6+
<?php
7+
$input = imagecreatefrompng(__DIR__ . '/gh10614.png');
8+
for ($angle = 0; $angle <= 270; $angle += 90) {
9+
$output = imagerotate($input, $angle, 0);
10+
}
11+
var_dump(imagescale($output, -1, 64, IMG_BICUBIC));
12+
?>
13+
--EXPECT--
14+
object(GdImage)#2 (0) {
15+
}

0 commit comments

Comments
 (0)