Skip to content

Commit 7f1fd06

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
2 parents cba92be + 7c43f68 commit 7f1fd06

File tree

3 files changed

+49
-17
lines changed

3 files changed

+49
-17
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ PHP NEWS
6161
fix backport from upstream). (David Carlier)
6262
. Fixed bug GH-12264 (overflow/underflow on imagerotate degrees value)
6363
(David Carlier)
64+
. Fixed bug GH-16274 (imagescale underflow on RBG channels /
65+
fix backport from upstream). (David Carlier)
6466

6567
- LDAP:
6668
. Fixed bug GH-16032 (Various NULL pointer dereferencements in

ext/gd/libgd/gd_interpolation.c

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

922+
static inline unsigned char
923+
uchar_clamp(double clr) {
924+
unsigned short result;
925+
assert(fabs(clr) <= SHRT_MAX);
926+
/* Casting a negative float to an unsigned short is undefined.
927+
* However, casting a float to a signed truncates toward zero and
928+
* casting a negative signed value to an unsigned of the same size
929+
* results in a bit-identical value (assuming twos-complement
930+
* arithmetic). This is what we want: all legal negative values
931+
* for clr will be greater than 255. */
932+
/* Convert and clamp. */
933+
result = (unsigned short)(short)(clr + 0.5);
934+
if (result > 255) {
935+
result = (clr < 0) ? 0 : 255;
936+
}/* if */
937+
return result;
938+
}/* uchar_clamp*/
939+
922940
static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImagePtr dst, unsigned int dst_width, unsigned int row, LineContribType *contrib)
923941
{
924942
int *p_src_row = pSrc->tpixels[row];
925943
int *p_dst_row = dst->tpixels[row];
926944
unsigned int x;
927945

928946
for (x = 0; x < dst_width; x++) {
929-
register unsigned char r = 0, g = 0, b = 0, a = 0;
947+
double r = 0, g = 0, b = 0, a = 0;
930948
const int left = contrib->ContribRow[x].Left;
931949
const int right = contrib->ContribRow[x].Right;
932-
int i;
950+
int i;
933951

934-
/* Accumulate each channel */
935-
for (i = left; i <= right; i++) {
936-
const int left_channel = i - left;
937-
r += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i])));
938-
g += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i])));
939-
b += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i])));
940-
a += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i])));
941-
}
942-
p_dst_row[x] = gdTrueColorAlpha(r, g, b, a);
952+
/* Accumulate each channel */
953+
for (i = left; i <= right; i++) {
954+
const int left_channel = i - left;
955+
r += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i]));
956+
g += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i]));
957+
b += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i]));
958+
a += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i]));
959+
}
960+
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
943961
}
944962
}
945963

@@ -972,7 +990,7 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
972990
{
973991
unsigned int y;
974992
for (y = 0; y < dst_height; y++) {
975-
register unsigned char r = 0, g = 0, b = 0, a = 0;
993+
double r = 0, g = 0, b = 0, a = 0;
976994
const int iLeft = contrib->ContribRow[y].Left;
977995
const int iRight = contrib->ContribRow[y].Right;
978996
int i;
@@ -981,12 +999,12 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
981999
for (i = iLeft; i <= iRight; i++) {
9821000
const int pCurSrc = pSrc->tpixels[i][uCol];
9831001
const int i_iLeft = i - iLeft;
984-
r += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc)));
985-
g += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc)));
986-
b += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc)));
987-
a += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc)));
1002+
r += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc));
1003+
g += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc));
1004+
b += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc));
1005+
a += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc));
9881006
}
989-
pRes->tpixels[y][uCol] = gdTrueColorAlpha(r, g, b, a);
1007+
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
9901008
}
9911009
}
9921010

ext/gd/tests/gh16257.phpt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
GH-16257 (underflow on RBG channels handling with imagescale)
3+
--EXTENSIONS--
4+
gd
5+
--FILE--
6+
<?php
7+
$im = imagecreatefromstring(file_get_contents(__DIR__ . '/imagecreatefromstring.gif'));
8+
imagescale($im, 32, 32, IMG_BICUBIC);
9+
echo "DONE";
10+
?>
11+
--EXPECT--
12+
DONE

0 commit comments

Comments
 (0)