Skip to content

Commit 7c43f68

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
2 parents 424fb2c + a2bdfef commit 7c43f68

File tree

3 files changed

+49
-17
lines changed

3 files changed

+49
-17
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ PHP NEWS
4242
fix backport from upstream). (David Carlier)
4343
. Fixed bug GH-12264 (overflow/underflow on imagerotate degrees value)
4444
(David Carlier)
45+
. Fixed bug GH-16274 (imagescale underflow on RBG channels /
46+
fix backport from upstream). (David Carlier)
4547

4648
- LDAP:
4749
. Fixed bug GH-16032 (Various NULL pointer dereferencements in

ext/gd/libgd/gd_interpolation.c

+35-17
Original file line numberDiff line numberDiff line change
@@ -929,27 +929,45 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi
929929
return res;
930930
}
931931

932+
static inline unsigned char
933+
uchar_clamp(double clr) {
934+
unsigned short result;
935+
assert(fabs(clr) <= SHRT_MAX);
936+
/* Casting a negative float to an unsigned short is undefined.
937+
* However, casting a float to a signed truncates toward zero and
938+
* casting a negative signed value to an unsigned of the same size
939+
* results in a bit-identical value (assuming twos-complement
940+
* arithmetic). This is what we want: all legal negative values
941+
* for clr will be greater than 255. */
942+
/* Convert and clamp. */
943+
result = (unsigned short)(short)(clr + 0.5);
944+
if (result > 255) {
945+
result = (clr < 0) ? 0 : 255;
946+
}/* if */
947+
return result;
948+
}/* uchar_clamp*/
949+
932950
static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImagePtr dst, unsigned int dst_width, unsigned int row, LineContribType *contrib)
933951
{
934952
int *p_src_row = pSrc->tpixels[row];
935953
int *p_dst_row = dst->tpixels[row];
936954
unsigned int x;
937955

938956
for (x = 0; x < dst_width; x++) {
939-
register unsigned char r = 0, g = 0, b = 0, a = 0;
957+
double r = 0, g = 0, b = 0, a = 0;
940958
const int left = contrib->ContribRow[x].Left;
941959
const int right = contrib->ContribRow[x].Right;
942-
int i;
960+
int i;
943961

944-
/* Accumulate each channel */
945-
for (i = left; i <= right; i++) {
946-
const int left_channel = i - left;
947-
r += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i])));
948-
g += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i])));
949-
b += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i])));
950-
a += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i])));
951-
}
952-
p_dst_row[x] = gdTrueColorAlpha(r, g, b, a);
962+
/* Accumulate each channel */
963+
for (i = left; i <= right; i++) {
964+
const int left_channel = i - left;
965+
r += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i]));
966+
g += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i]));
967+
b += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i]));
968+
a += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i]));
969+
}
970+
p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
953971
}
954972
}
955973

@@ -982,7 +1000,7 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
9821000
{
9831001
unsigned int y;
9841002
for (y = 0; y < dst_height; y++) {
985-
register unsigned char r = 0, g = 0, b = 0, a = 0;
1003+
double r = 0, g = 0, b = 0, a = 0;
9861004
const int iLeft = contrib->ContribRow[y].Left;
9871005
const int iRight = contrib->ContribRow[y].Right;
9881006
int i;
@@ -991,12 +1009,12 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag
9911009
for (i = iLeft; i <= iRight; i++) {
9921010
const int pCurSrc = pSrc->tpixels[i][uCol];
9931011
const int i_iLeft = i - iLeft;
994-
r += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc)));
995-
g += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc)));
996-
b += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc)));
997-
a += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc)));
1012+
r += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc));
1013+
g += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc));
1014+
b += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc));
1015+
a += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc));
9981016
}
999-
pRes->tpixels[y][uCol] = gdTrueColorAlpha(r, g, b, a);
1017+
pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a));
10001018
}
10011019
}
10021020

ext/gd/tests/gh16257.phpt

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