Skip to content

Commit 9bb076f

Browse files
araptejohanvos
authored andcommittedApr 16, 2024
8313064: General enhancements of image handling
Reviewed-by: rhalade, jdv, kcr
1 parent 195c422 commit 9bb076f

File tree

9 files changed

+192
-87
lines changed

9 files changed

+192
-87
lines changed
 

‎modules/javafx.graphics/src/main/native-glass/win/Pixels.cpp

+30-4
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,36 @@
3232

3333
Bitmap::Bitmap(int width, int height)
3434
{
35-
BYTE *mpixels = new BYTE[width * height];
36-
memset(mpixels, 0, width * height);
37-
Attach(::CreateBitmap(width, height, 1, 1, mpixels));
38-
delete[] mpixels;
35+
if (width <= 0 || height <= 0) {
36+
return;
37+
}
38+
39+
int numPlanes = 1;
40+
int bitCount = 1; // monochrome bitmap
41+
// refer : Doc of ::CreateBitmap(): Each scan line in the rectangle must be word aligned
42+
if (width > INT_MAX - 15) {
43+
fprintf(stderr, "Bitmap: Failed to create monochrome bitmap for icon.\n");
44+
return;
45+
}
46+
int scanLength = (((width * numPlanes * bitCount + 15) >> 4) << 1);
47+
48+
if (scanLength > INT_MAX / height) {
49+
fprintf(stderr, "Bitmap: Failed to create monochrome bitmap for icon.\n");
50+
return;
51+
}
52+
53+
int bufSize = scanLength * height;
54+
BYTE *mpixels = new BYTE[bufSize];
55+
if (mpixels != NULL) {
56+
memset(mpixels, 0, bufSize);
57+
HBITMAP bmp = ::CreateBitmap(width, height, numPlanes, bitCount, mpixels);
58+
if (bmp != NULL) {
59+
Attach(bmp);
60+
} else {
61+
fprintf(stderr, "Bitmap: Failed to create monochrome bitmap for icon.\n");
62+
}
63+
delete[] mpixels;
64+
}
3965
ASSERT((HBITMAP)*this);
4066
}
4167

‎modules/javafx.graphics/src/main/native-glass/win/Utils.h

+56-15
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,15 @@ class DNTString {
124124
DNTString(int limit) :
125125
m_limit(limit), m_length(0), m_substrings(NULL), m_count(0)
126126
{
127+
if (limit < MIN_LIMIT) {
128+
m_limit = limit = MIN_LIMIT;
129+
}
127130
wszStr = new wchar_t[limit];
128-
memset(wszStr, 0, limit*sizeof(wchar_t));
131+
if (wszStr) {
132+
memset(wszStr, 0, limit * sizeof(wchar_t));
133+
} else {
134+
m_limit = MIN_LIMIT;
135+
}
129136
}
130137
~DNTString() {
131138
if (wszStr) {
@@ -146,17 +153,25 @@ class DNTString {
146153
wchar_t * const oldStr = wszStr;
147154
const size_t oldLimit = m_limit;
148155

156+
if (limit < MIN_LIMIT) {
157+
limit = MIN_LIMIT;
158+
}
149159
m_limit = limit;
150-
wszStr = new wchar_t[limit];
151-
memset(wszStr, 0, limit*sizeof(wchar_t));
160+
wszStr = new wchar_t[m_limit];
161+
if (wszStr) {
162+
memset(wszStr, 0, m_limit * sizeof(wchar_t));
152163

153-
if (copy && oldStr) {
154-
wmemcpy_s(wszStr, m_limit - 1, oldStr, min(oldLimit - 1, m_limit - 1));
155-
m_length = min(m_length, m_limit - 2);
156-
}
164+
if (copy && oldStr) {
165+
wmemcpy_s(wszStr, m_limit - 1, oldStr, min(oldLimit - 1, m_limit - 1));
166+
m_length = min(m_length, m_limit - MIN_LIMIT);
167+
}
157168

158-
if (oldStr) {
159-
delete[] oldStr;
169+
if (oldStr) {
170+
delete[] oldStr;
171+
}
172+
} else {
173+
wszStr = oldStr;
174+
m_limit = oldLimit;
160175
}
161176
}
162177

@@ -166,31 +181,53 @@ class DNTString {
166181
}
167182

168183
wchar_t* substring(UINT i) {
184+
if (wszStr == NULL) {
185+
return NULL;
186+
}
169187
calculateSubstrings();
170188
return wszStr+m_substrings[i];
171189
}
172190

173191
// appends the count characters of the src string to the DNT string
174192
void append(const wchar_t *wszSrc, const size_t count, bool allowGrow = false) {
193+
if (wszSrc == NULL) {
194+
return;
195+
}
175196
if (allowGrow) {
197+
if (count > SIZE_MAX - m_length - 2) {
198+
return;
199+
}
176200
if (m_length + count > m_limit - 2) {
177201
const size_t GROWTH_RATE = 2; // consider parameterizing this const
178202

179-
setLimit((m_length + count + 2)*GROWTH_RATE, true);
203+
if ((m_length + count + 2) < (SIZE_MAX / GROWTH_RATE)) {
204+
setLimit((m_length + count + 2) * GROWTH_RATE, true);
205+
} else {
206+
setLimit((m_length + count + 2), true);
207+
}
180208
}
181209
}
182210

183-
// "-1" because this is a _double_ null terminated string
184-
wcsncpy_s(wszStr + m_length, m_limit - m_length - 1, wszSrc, count);
185-
m_length += count;
186-
if (m_length > m_limit) {
187-
m_length = m_limit;
211+
if (m_limit - m_length - 1 >= count) {
212+
// "-1" because this is a _double_ null terminated string
213+
int res = wcsncpy_s(wszStr + m_length, m_limit - m_length - 1, wszSrc, count);
214+
if (res == 0) { // wcsncpy_s succeeded
215+
m_length += count;
216+
if (m_length > m_limit) {
217+
m_length = m_limit;
218+
}
219+
} else {
220+
m_length = 0;
221+
}
188222
}
189223
}
190224

191225
// recalculates the length of the DNT string
192226
// use the function when wszStr could be modified directly
193227
void calculateLength() {
228+
if (wszStr == NULL) {
229+
return;
230+
}
194231
size_t i = 0;
195232
while(wszStr[i] != L'\0' || wszStr[i+1] != L'\0') {
196233
i++;
@@ -205,6 +242,9 @@ class DNTString {
205242
private:
206243

207244
void calculateSubstrings() {
245+
if (wszStr == NULL) {
246+
return;
247+
}
208248
if (m_substrings)
209249
return;
210250

@@ -230,6 +270,7 @@ class DNTString {
230270

231271
wchar_t *wszStr;
232272
size_t m_length, m_limit;
273+
static const size_t MIN_LIMIT = 2;
233274

234275
size_t *m_substrings;
235276
UINT m_count; // the count of the substrings

‎modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.cc

+21-22
Original file line numberDiff line numberDiff line change
@@ -629,24 +629,27 @@ HRESULT D3DContext::setDeviceParametersFor3D() {
629629
return res;
630630
}
631631

632-
/*
633-
* Note: this method assumes that pIndices is not null
634-
*/
635-
static HRESULT fillQuadIndices(IDirect3DIndexBuffer9 *pIndices, int maxQuads) {
636-
short * data = 0;
637-
HRESULT hr = pIndices->Lock(0, maxQuads * 6 * sizeof(short), (void **)&data, 0);
638-
if (SUCCEEDED(hr) && data) {
639-
for (int i = 0; i != maxQuads; ++i) {
640-
int vtx = i * 4;
641-
int idx = i * 6;
642-
data[idx + 0] = vtx + 0;
643-
data[idx + 1] = vtx + 1;
644-
data[idx + 2] = vtx + 2;
645-
data[idx + 3] = vtx + 2;
646-
data[idx + 4] = vtx + 1;
647-
data[idx + 5] = vtx + 3;
632+
HRESULT D3DContext::createIndexBuffer() {
633+
RETURN_STATUS_IF_NULL(pd3dDevice, S_FALSE);
634+
HRESULT hr = pd3dDevice->CreateIndexBuffer(sizeof(short) * 6 * MAX_BATCH_QUADS,
635+
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, getResourcePool(), &pIndices, 0);
636+
// fill index buffer
637+
if (hr == D3D_OK && pIndices) {
638+
short* data = 0;
639+
hr = pIndices->Lock(0, 0, (void **)&data, 0);
640+
if (SUCCEEDED(hr) && data) {
641+
for (int i = 0; i < MAX_BATCH_QUADS; i++) {
642+
int vtx = i * 4;
643+
int idx = i * 6;
644+
data[idx + 0] = vtx + 0;
645+
data[idx + 1] = vtx + 1;
646+
data[idx + 2] = vtx + 2;
647+
data[idx + 3] = vtx + 2;
648+
data[idx + 4] = vtx + 1;
649+
data[idx + 5] = vtx + 3;
650+
}
651+
hr = pIndices->Unlock();
648652
}
649-
hr = pIndices->Unlock();
650653
}
651654
return hr;
652655
}
@@ -699,11 +702,7 @@ HRESULT D3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice)
699702
// RETURN_STATUS_IF_FAILED(res);
700703

701704
if (pIndices == NULL) {
702-
res = pd3dDevice->CreateIndexBuffer(sizeof(short) * 6 * MAX_BATCH_QUADS,
703-
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, getResourcePool(), &pIndices, 0);
704-
if (pIndices) {
705-
res = fillQuadIndices(pIndices, MAX_BATCH_QUADS);
706-
}
705+
res = createIndexBuffer();
707706
RETURN_STATUS_IF_FAILED(res);
708707
}
709708
// res = pd3dDevice->SetIndices(pIndices);

‎modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.h

+1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ class D3DContext {
261261

262262
D3DContext(IDirect3D9 *pd3d, IDirect3D9Ex *pd3dEx, UINT adapter);
263263
HRESULT InitDevice(IDirect3DDevice9 *d3dDevice);
264+
HRESULT createIndexBuffer();
264265
HRESULT InitContextCaps();
265266
IDirect3DDevice9 *pd3dDevice;
266267
IDirect3DDevice9Ex *pd3dDeviceEx;

‎modules/javafx.graphics/src/main/native-prism-es2/GLContext.c

+5
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,11 @@ jboolean doReadPixels(JNIEnv *env, jlong nativeCtxInfo, jint length, jobject buf
10111011
return JNI_FALSE;
10121012
}
10131013

1014+
if (width <= 0 || height <= 0) {
1015+
fprintf(stderr, "doReadPixels: width or height is <= 0\n");
1016+
return JNI_FALSE;
1017+
}
1018+
10141019
// sanity check, do we have enough memory
10151020
// length, width and height are non-negative
10161021
if ((length / 4 / width) < height) {

‎modules/javafx.graphics/src/main/native-prism-sw/JAbstractSurface.c

+47-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <PiscesSysutils.h>
3030

3131
#include <PiscesSurface.inl>
32+
#include <limits.h>
3233

3334
#define SURFACE_NATIVE_PTR 0
3435
#define SURFACE_LAST SURFACE_NATIVE_PTR
@@ -74,12 +75,33 @@ Java_com_sun_pisces_AbstractSurface_getRGBImpl(JNIEnv* env, jobject objectHandle
7475
(*env)->GetLongField(env, objectHandle,
7576
fieldIds[SURFACE_NATIVE_PTR]));
7677

77-
CORRECT_DIMS(surface, x, y, width, height, dstX, dstY);
78+
if (surface == NULL) {
79+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Invalid surface");
80+
return;
81+
}
82+
int surfaceWidth = surface->width;
83+
int surfaceHeight = surface->height;
84+
if (x < 0 || x >= surfaceWidth ||
85+
y < 0 || y >= surfaceHeight ||
86+
width < 0 || width > (surfaceWidth - x) ||
87+
height < 0 || height > (surfaceHeight - y) ||
88+
scanLength < width) {
89+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Illegal arguments");
90+
return;
91+
}
7892

7993
if ((width > 0) && (height > 0)) {
8094
jint* dstData;
8195
jsize dstDataLength = (*env)->GetArrayLength(env, arrayHandle);
96+
if (dstY > ((INT_MAX - offset - dstX) / scanLength)) {
97+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of bounds offset or scan length");
98+
return;
99+
}
82100
jint dstStart = offset + dstY * scanLength + dstX;
101+
if (scanLength > ((INT_MAX - dstStart) / height)) {
102+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of bounds offset or scan length");
103+
return;
104+
}
83105
jint dstEnd = dstStart + height * scanLength - 1;
84106
if ((dstStart < 0) || (dstStart >= dstDataLength) || (dstEnd < 0) || (dstEnd >= dstDataLength)) {
85107
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of range access of buffer");
@@ -130,12 +152,35 @@ Java_com_sun_pisces_AbstractSurface_setRGBImpl(JNIEnv* env, jobject objectHandle
130152
(*env)->GetLongField(env, objectHandle,
131153
fieldIds[SURFACE_NATIVE_PTR]));
132154

133-
CORRECT_DIMS(surface, x, y, width, height, srcX, srcY);
155+
if (surface == NULL) {
156+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Invalid surface");
157+
return;
158+
}
159+
int surfaceWidth = surface->width;
160+
int surfaceHeight = surface->height;
161+
if (x < 0 || x >= surfaceWidth ||
162+
y < 0 || y >= surfaceHeight ||
163+
width < 0 || width > (surfaceWidth - x) ||
164+
height < 0 || height > (surfaceHeight - y) ||
165+
scanLength < width) {
166+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Illegal arguments");
167+
return;
168+
}
134169

135170
if ((width > 0) && (height > 0)) {
136171
jint* srcData;
137172
jsize srcDataLength = (*env)->GetArrayLength(env, arrayHandle);
173+
174+
if (srcY > ((INT_MAX - offset - srcX) / scanLength)) {
175+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of bounds offset or scan length");
176+
return;
177+
}
138178
jint srcStart = offset + srcY * scanLength + srcX;
179+
180+
if (scanLength > ((INT_MAX - srcStart) / height)) {
181+
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "Out of bounds offset or scan length");
182+
return;
183+
}
139184
jint srcEnd = srcStart + height * scanLength - 1;
140185
if ((srcStart < 0) || (srcStart >= srcDataLength) || (srcEnd < 0) || (srcEnd >= srcDataLength)) {
141186
JNI_ThrowNew(env, "java/lang/IllegalArgumentException", "out of range access of buffer");

‎modules/javafx.graphics/src/main/native-prism-sw/JPiscesRenderer.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -248,13 +248,17 @@ JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_setTextureImpl
248248
{
249249
Renderer* rdr;
250250
Transform6 textureTransform;
251-
jint *data;
251+
jint *data = NULL;
252+
jsize dataLength = (*env)->GetArrayLength(env, dataArray);
252253

253-
transform_get6(&textureTransform, env, jTransform);
254+
if (width > 0 && height > 0 && (width < (INT_MAX / height / sizeof(jint)))
255+
&& stride > 0 && (height - 1) <= (dataLength - width) / stride) {
256+
transform_get6(&textureTransform, env, jTransform);
254257

255-
rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR]));
258+
rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR]));
256259

257-
data = (jint*)(*env)->GetPrimitiveArrayCritical(env, dataArray, NULL);
260+
data = (jint*)(*env)->GetPrimitiveArrayCritical(env, dataArray, NULL);
261+
}
258262
if (data != NULL) {
259263
jint *alloc_data = my_malloc(jint, width * height);
260264
if (alloc_data != NULL) {

‎modules/javafx.graphics/src/main/native-prism-sw/PiscesPaint.c

+24-22
Original file line numberDiff line numberDiff line change
@@ -1121,30 +1121,32 @@ genTexturePaintMultiply(Renderer *rdr, jint height) {
11211121
break;
11221122
case PAINT_LINEAR_GRADIENT:
11231123
case PAINT_RADIAL_GRADIENT:
1124-
{
1125-
jint *imagePaint = my_malloc(jint, w * height);
1126-
if (imagePaint != NULL) {
1127-
if (rdr->_prevPaintMode == PAINT_LINEAR_GRADIENT) {
1128-
genLinearGradientPaint(rdr, height);
1129-
} else {
1130-
genRadialGradientPaint(rdr, height);
1131-
}
1132-
genTexturePaintTarget(rdr, imagePaint, height);
1133-
for (i = 0; i < height; i++) {
1134-
idx = i * paintStride;
1135-
for (j = 0; j < w; j++) {
1136-
pval = paint[idx + j];
1137-
tval = imagePaint[idx + j];
1138-
palpha_1 = ((pval >> 24) & 0xFF) + 1;
1139-
oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8;
1140-
ored = ((((((pval >> 16) & 0xFF) + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8;
1141-
ogreen = ((((((pval >> 8) & 0xFF) + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8;
1142-
oblue = (((((pval & 0xFF) + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8;
1143-
paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue;
1124+
if (w > 0 && height > 0 && (w < (INT_MAX / height / sizeof(jint)))) {
1125+
jint *imagePaint = my_malloc(jint, w * height);
1126+
if (imagePaint != NULL) {
1127+
if (rdr->_prevPaintMode == PAINT_LINEAR_GRADIENT) {
1128+
genLinearGradientPaint(rdr, height);
1129+
} else {
1130+
genRadialGradientPaint(rdr, height);
11441131
}
1132+
genTexturePaintTarget(rdr, imagePaint, height);
1133+
for (i = 0; i < height; i++) {
1134+
idx = i * paintStride;
1135+
for (j = 0; j < w; j++) {
1136+
pval = paint[idx + j];
1137+
tval = imagePaint[idx + j];
1138+
palpha_1 = ((pval >> 24) & 0xFF) + 1;
1139+
oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8;
1140+
ored = ((((((pval >> 16) & 0xFF) + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8;
1141+
ogreen = ((((((pval >> 8) & 0xFF) + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8;
1142+
oblue = (((((pval & 0xFF) + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8;
1143+
paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue;
1144+
}
1145+
}
1146+
my_free(imagePaint);
11451147
}
1146-
my_free(imagePaint);
1147-
}
1148+
} else {
1149+
fprintf(stderr, "Invalid dimensions: width: %d, height: %d\n", w, height);
11481150
}
11491151
break;
11501152
}

‎modules/javafx.graphics/src/main/native-prism-sw/PiscesSurface.h

-18
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,6 @@
6262
*/
6363
#define TYPE_INT_ARGB_PRE com_sun_pisces_RendererBase_TYPE_INT_ARGB_PRE
6464

65-
#define CORRECT_DIMS(_surface, _x, _y, _w, _h, _x1, _y1) \
66-
if (_x < 0) { \
67-
_x1 -= _x; \
68-
_w += _x; \
69-
_x = 0; \
70-
} \
71-
if (_y < 0) { \
72-
_y1 -= _y; \
73-
_h += _y; \
74-
_y = 0; \
75-
} \
76-
if ((_x + _w) > (_surface)->width) { \
77-
_w = (_surface)->width - _x; \
78-
} \
79-
if ((_y + _h) > (_surface)->height) { \
80-
_h = (_surface)->height - _y; \
81-
}
82-
8365
typedef struct _Surface {
8466
jint width;
8567
jint height;

0 commit comments

Comments
 (0)
Please sign in to comment.