Skip to content

Commit 6d6afd9

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix GH-16559: UBSan abort in ext/gd/libgd/gd_interpolation.c:1007
2 parents 301cda9 + e1e1e64 commit 6d6afd9

File tree

3 files changed

+35
-6
lines changed

3 files changed

+35
-6
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ PHP NEWS
5757
. Fixed bug GH-16334 (imageaffine overflow on matrix elements).
5858
(David Carlier)
5959
. Fixed bug GH-16427 (Unchecked libavif return values). (cmb)
60+
. Fixed bug GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007).
61+
(nielsdos)
6062

6163
- GMP:
6264
. Fixed floating point exception bug with gmp_pow when using

ext/gd/libgd/gd_interpolation.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -929,21 +929,29 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
929929
return res;
930930
}
931931

932+
/* Convert a double to an unsigned char, rounding to the nearest
933+
* integer and clamping the result between 0 and max. The absolute
934+
* value of clr must be less than the maximum value of an unsigned
935+
* short. */
932936
static inline unsigned char
933-
uchar_clamp(double clr) {
937+
uchar_clamp(double clr, unsigned char max) {
934938
unsigned short result;
935-
assert(fabs(clr) <= SHRT_MAX);
939+
940+
//assert(fabs(clr) <= SHRT_MAX);
941+
936942
/* Casting a negative float to an unsigned short is undefined.
937943
* However, casting a float to a signed truncates toward zero and
938944
* casting a negative signed value to an unsigned of the same size
939945
* results in a bit-identical value (assuming twos-complement
940946
* arithmetic). This is what we want: all legal negative values
941947
* for clr will be greater than 255. */
948+
942949
/* Convert and clamp. */
943950
result = (unsigned short)(short)(clr + 0.5);
944-
if (result > 255) {
945-
result = (clr < 0) ? 0 : 255;
951+
if (result > max) {
952+
result = (clr < 0) ? 0 : max;
946953
}/* if */
954+
947955
return result;
948956
}/* uchar_clamp*/
949957

@@ -967,7 +975,9 @@ static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImage
967975
b += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i]));
968976
a += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i]));
969977
}
970-
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
978+
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF),
979+
uchar_clamp(b, 0xFF),
980+
uchar_clamp(a, 0x7F)); /* alpha is 0..127 */
971981
}
972982
}
973983

@@ -1014,7 +1024,9 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
10141024
b += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc));
10151025
a += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc));
10161026
}
1017-
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
1027+
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF),
1028+
uchar_clamp(b, 0xFF),
1029+
uchar_clamp(a, 0x7F)); /* alpha is 0..127 */
10181030
}
10191031
}
10201032

ext/gd/tests/gh16559.phpt

+15
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)