Skip to content

Commit 93c0ce9

Browse files
committed
[Win32] Ensure Image#getImageData() returns no internal data
A caching mechanism for ImageData introduced to some provider implementations inside the Image class leads to Image#getImageData() returning an ImageData object, which if modified affects the underlying Image. This contradicts the contract of that method, which states that changes to that object will not affect the Image. This change ensures that Image#getImagetData() only returns objects that are not used internal of the Image instance. To this end, clones of the ImageData are created where necessary.
1 parent a641cdb commit 93c0ce9

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,7 +2017,7 @@ ImageData newImageData(ZoomContext zoomContext) {
20172017
handle.destroy();
20182018
return data;
20192019
};
2020-
return cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrieval);
2020+
return (ImageData) cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrieval).clone();
20212021
}
20222022

20232023
@Override
@@ -2297,7 +2297,7 @@ ImageData newImageData(ZoomContext zoomContext) {
22972297
handle.destroy();
22982298
return data;
22992299
};
2300-
return cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrival);
2300+
return (ImageData) cachedImageData.computeIfAbsent(zoomContext.targetZoom(), imageDataRetrival).clone();
23012301
}
23022302

23032303

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_Image.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import static org.junit.Assert.assertFalse;
2121
import static org.junit.Assert.assertNotNull;
2222
import static org.junit.Assert.assertNull;
23-
import static org.junit.Assert.assertSame;
2423
import static org.junit.Assert.assertThrows;
2524
import static org.junit.Assert.assertTrue;
2625
import static org.junit.Assume.assumeFalse;
@@ -33,6 +32,8 @@
3332
import java.nio.file.Files;
3433
import java.nio.file.Path;
3534
import java.util.Comparator;
35+
import java.util.List;
36+
import java.util.concurrent.atomic.AtomicInteger;
3637
import java.util.function.Consumer;
3738

3839
import org.eclipse.swt.SWT;
@@ -683,6 +684,25 @@ public void test_getImageData() {
683684
getImageData2(32, new PaletteData(0xff0000, 0xff00, 0xff));
684685
}
685686

687+
@Test
688+
public void test_getImageData_changingImageDataDoesNotAffectImage() {
689+
List<Image> images = List.of( //
690+
new Image(display, imageFileNameProvider), //
691+
new Image(display, imageDataProvider), //
692+
new Image(display, new ImageData(10, 10, 32, new PaletteData(0xff0000, 0xff00, 0xff))) //
693+
);
694+
695+
try {
696+
for (Image image : images) {
697+
ImageData originalImageData = image.getImageData();
698+
originalImageData.setPixel(0, 0, originalImageData.getPixel(0, 0) + 1);
699+
assertNotEquals(image.getImageData().getPixel(0, 0), originalImageData.getPixel(0, 0));
700+
}
701+
} finally {
702+
images.forEach(Image::dispose);
703+
}
704+
}
705+
686706
@Test
687707
public void test_getImageData_100() {
688708
getImageData_int(100);
@@ -1032,11 +1052,17 @@ public void test_updateWidthHeightAfterDPIChange() {
10321052
public void test_imageDataIsCached() {
10331053
assumeTrue("On-demand image creation only implemented for Windows", SwtTestUtil.isWindows);
10341054
String imagePath = getPath("collapseall.png");
1055+
AtomicInteger callCount = new AtomicInteger();
10351056
ImageFileNameProvider imageFileNameProvider = __ -> {
1057+
callCount.incrementAndGet();
10361058
return imagePath;
10371059
};
10381060
Image fileNameProviderImage = new Image(display, imageFileNameProvider);
1039-
assertSame(fileNameProviderImage.getImageData(100), fileNameProviderImage.getImageData(100));
1061+
callCount.set(0);
1062+
fileNameProviderImage.getImageData(100);
1063+
fileNameProviderImage.getImageData(100);
1064+
fileNameProviderImage.getImageData(100);
1065+
assertEquals(0, callCount.get());
10401066
}
10411067

10421068
@Test

0 commit comments

Comments
 (0)