Skip to content

Commit 4841715

Browse files
tcl3shannonbooth
authored andcommitted
LibWeb: Don't crash when creating empty bitmap from a HTMLCanvasElement
1 parent bd83f5b commit 4841715

File tree

10 files changed

+527
-2
lines changed

10 files changed

+527
-2
lines changed

Libraries/LibWeb/HTML/ImageBitmap.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ void ImageBitmap::close()
143143
void ImageBitmap::set_bitmap(RefPtr<Gfx::Bitmap> bitmap)
144144
{
145145
m_bitmap = move(bitmap);
146-
m_width = m_bitmap->width();
147-
m_height = m_bitmap->height();
146+
m_width = m_bitmap ? m_bitmap->width() : 0;
147+
m_height = m_bitmap ? m_bitmap->height() : 0;
148148
}
149149

150150
Gfx::Bitmap* ImageBitmap::bitmap() const
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
Harness status: OK
2+
3+
Found 93 tests
4+
5+
57 Pass
6+
36 Fail
7+
Pass createImageBitmap with an HTMLCanvasElement source and sw set to 0
8+
Pass createImageBitmap with an HTMLCanvasElement source and sh set to 0
9+
Fail createImageBitmap with an HTMLCanvasElement source and oversized (unallocatable) crop region
10+
Pass createImageBitmap with an HTMLCanvasElement source and a value of 0 int resizeWidth
11+
Pass createImageBitmap with an HTMLCanvasElement source and a value of 0 in resizeHeight
12+
Pass createImageBitmap with an HTMLCanvasElement source and a value between 0 and 1 in resizeWidth
13+
Pass createImageBitmap with an HTMLCanvasElement source and a value between 0 and 1 in resizeHeight
14+
Pass createImageBitmap with an HTMLVideoElement source and sw set to 0
15+
Pass createImageBitmap with an HTMLVideoElement source and sh set to 0
16+
Fail createImageBitmap with an HTMLVideoElement source and oversized (unallocatable) crop region
17+
Fail createImageBitmap with an HTMLVideoElement source and a value of 0 int resizeWidth
18+
Fail createImageBitmap with an HTMLVideoElement source and a value of 0 in resizeHeight
19+
Fail createImageBitmap with an HTMLVideoElement source and a value between 0 and 1 in resizeWidth
20+
Fail createImageBitmap with an HTMLVideoElement source and a value between 0 and 1 in resizeHeight
21+
Pass createImageBitmap with an HTMLVideoElement from a data URL source and sw set to 0
22+
Pass createImageBitmap with an HTMLVideoElement from a data URL source and sh set to 0
23+
Fail createImageBitmap with an HTMLVideoElement from a data URL source and oversized (unallocatable) crop region
24+
Fail createImageBitmap with an HTMLVideoElement from a data URL source and a value of 0 int resizeWidth
25+
Fail createImageBitmap with an HTMLVideoElement from a data URL source and a value of 0 in resizeHeight
26+
Fail createImageBitmap with an HTMLVideoElement from a data URL source and a value between 0 and 1 in resizeWidth
27+
Fail createImageBitmap with an HTMLVideoElement from a data URL source and a value between 0 and 1 in resizeHeight
28+
Pass createImageBitmap with a bitmap HTMLImageElement source and sw set to 0
29+
Pass createImageBitmap with a bitmap HTMLImageElement source and sh set to 0
30+
Fail createImageBitmap with a bitmap HTMLImageElement source and oversized (unallocatable) crop region
31+
Fail createImageBitmap with a bitmap HTMLImageElement source and a value of 0 int resizeWidth
32+
Fail createImageBitmap with a bitmap HTMLImageElement source and a value of 0 in resizeHeight
33+
Fail createImageBitmap with a bitmap HTMLImageElement source and a value between 0 and 1 in resizeWidth
34+
Fail createImageBitmap with a bitmap HTMLImageElement source and a value between 0 and 1 in resizeHeight
35+
Pass createImageBitmap with a vector HTMLImageElement source and sw set to 0
36+
Pass createImageBitmap with a vector HTMLImageElement source and sh set to 0
37+
Pass createImageBitmap with a vector HTMLImageElement source and oversized (unallocatable) crop region
38+
Pass createImageBitmap with a vector HTMLImageElement source and a value of 0 int resizeWidth
39+
Pass createImageBitmap with a vector HTMLImageElement source and a value of 0 in resizeHeight
40+
Pass createImageBitmap with a vector HTMLImageElement source and a value between 0 and 1 in resizeWidth
41+
Pass createImageBitmap with a vector HTMLImageElement source and a value between 0 and 1 in resizeHeight
42+
Pass createImageBitmap with a bitmap SVGImageElement source and sw set to 0
43+
Pass createImageBitmap with a bitmap SVGImageElement source and sh set to 0
44+
Fail createImageBitmap with a bitmap SVGImageElement source and oversized (unallocatable) crop region
45+
Fail createImageBitmap with a bitmap SVGImageElement source and a value of 0 int resizeWidth
46+
Fail createImageBitmap with a bitmap SVGImageElement source and a value of 0 in resizeHeight
47+
Fail createImageBitmap with a bitmap SVGImageElement source and a value between 0 and 1 in resizeWidth
48+
Fail createImageBitmap with a bitmap SVGImageElement source and a value between 0 and 1 in resizeHeight
49+
Pass createImageBitmap with a vector SVGImageElement source and sw set to 0
50+
Pass createImageBitmap with a vector SVGImageElement source and sh set to 0
51+
Pass createImageBitmap with a vector SVGImageElement source and oversized (unallocatable) crop region
52+
Pass createImageBitmap with a vector SVGImageElement source and a value of 0 int resizeWidth
53+
Pass createImageBitmap with a vector SVGImageElement source and a value of 0 in resizeHeight
54+
Pass createImageBitmap with a vector SVGImageElement source and a value between 0 and 1 in resizeWidth
55+
Pass createImageBitmap with a vector SVGImageElement source and a value between 0 and 1 in resizeHeight
56+
Pass createImageBitmap with an OffscreenCanvas source and sw set to 0
57+
Pass createImageBitmap with an OffscreenCanvas source and sh set to 0
58+
Fail createImageBitmap with an OffscreenCanvas source and oversized (unallocatable) crop region
59+
Fail createImageBitmap with an OffscreenCanvas source and a value of 0 int resizeWidth
60+
Fail createImageBitmap with an OffscreenCanvas source and a value of 0 in resizeHeight
61+
Fail createImageBitmap with an OffscreenCanvas source and a value between 0 and 1 in resizeWidth
62+
Fail createImageBitmap with an OffscreenCanvas source and a value between 0 and 1 in resizeHeight
63+
Pass createImageBitmap with an ImageData source and sw set to 0
64+
Pass createImageBitmap with an ImageData source and sh set to 0
65+
Fail createImageBitmap with an ImageData source and oversized (unallocatable) crop region
66+
Pass createImageBitmap with an ImageData source and a value of 0 int resizeWidth
67+
Pass createImageBitmap with an ImageData source and a value of 0 in resizeHeight
68+
Pass createImageBitmap with an ImageData source and a value between 0 and 1 in resizeWidth
69+
Pass createImageBitmap with an ImageData source and a value between 0 and 1 in resizeHeight
70+
Pass createImageBitmap with an ImageBitmap source and sw set to 0
71+
Pass createImageBitmap with an ImageBitmap source and sh set to 0
72+
Fail createImageBitmap with an ImageBitmap source and oversized (unallocatable) crop region
73+
Fail createImageBitmap with an ImageBitmap source and a value of 0 int resizeWidth
74+
Fail createImageBitmap with an ImageBitmap source and a value of 0 in resizeHeight
75+
Fail createImageBitmap with an ImageBitmap source and a value between 0 and 1 in resizeWidth
76+
Fail createImageBitmap with an ImageBitmap source and a value between 0 and 1 in resizeHeight
77+
Pass createImageBitmap with a Blob source and sw set to 0
78+
Pass createImageBitmap with a Blob source and sh set to 0
79+
Fail createImageBitmap with a Blob source and oversized (unallocatable) crop region
80+
Pass createImageBitmap with a Blob source and a value of 0 int resizeWidth
81+
Pass createImageBitmap with a Blob source and a value of 0 in resizeHeight
82+
Pass createImageBitmap with a Blob source and a value between 0 and 1 in resizeWidth
83+
Pass createImageBitmap with a Blob source and a value between 0 and 1 in resizeHeight
84+
Pass createImageBitmap with undefined image source.
85+
Pass createImageBitmap with null image source.
86+
Pass createImageBitmap with CanvasRenderingContext2D image source.
87+
Pass createImageBitmap with WebGLRenderingContext image source.
88+
Pass createImageBitmap with Uint8Array image source.
89+
Pass createImageBitmap with ArrayBuffer image source.
90+
Pass createImageBitmap with empty image source.
91+
Pass createImageBitmap with empty video source.
92+
Fail createImageBitmap with an oversized canvas source.
93+
Fail createImageBitmap with an invalid OffscreenCanvas source.
94+
Pass createImageBitmap with an undecodable blob source.
95+
Pass createImageBitmap with a broken image source.
96+
Fail createImageBitmap with an available but undecodable image source.
97+
Pass createImageBitmap with an available but zero height image source.
98+
Pass createImageBitmap with an available but zero width image source.
99+
Pass createImageBitmap with a closed ImageBitmap.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
function makeCanvas() {
2+
return new Promise(resolve => {
3+
var testCanvas = document.createElement("canvas");
4+
testCanvas.width = 20;
5+
testCanvas.height = 20;
6+
var testCtx = testCanvas.getContext("2d");
7+
testCtx.fillStyle = "rgb(255, 0, 0)";
8+
testCtx.fillRect(0, 0, 10, 10);
9+
testCtx.fillStyle = "rgb(0, 255, 0)";
10+
testCtx.fillRect(10, 0, 10, 10);
11+
testCtx.fillStyle = "rgb(0, 0, 255)";
12+
testCtx.fillRect(0, 10, 10, 10);
13+
testCtx.fillStyle = "rgb(0, 0, 0)";
14+
testCtx.fillRect(10, 10, 10, 10);
15+
resolve(testCanvas);
16+
});
17+
}
18+
19+
function makeOffscreenCanvas() {
20+
return new Promise(resolve => {
21+
let canvas = new OffscreenCanvas(20, 20);
22+
var testCtx = canvas.getContext("2d");
23+
testCtx.fillStyle = "rgb(255, 0, 0)";
24+
testCtx.fillRect(0, 0, 10, 10);
25+
testCtx.fillStyle = "rgb(0, 255, 0)";
26+
testCtx.fillRect(10, 0, 10, 10);
27+
testCtx.fillStyle = "rgb(0, 0, 255)";
28+
testCtx.fillRect(0, 10, 10, 10);
29+
testCtx.fillStyle = "rgb(0, 0, 0)";
30+
testCtx.fillRect(10, 10, 10, 10);
31+
resolve(canvas);
32+
});
33+
}
34+
35+
function makeMakeVideo(src) {
36+
return function () {
37+
return new Promise(function(resolve, reject) {
38+
var video = document.createElement("video");
39+
video.oncanplaythrough = function() {
40+
resolve(video);
41+
};
42+
video.onerror = reject;
43+
44+
// preload=auto is required to ensure a frame is available once
45+
// canplaythrough is fired. The default of preload=metadata does not
46+
// gaurantee this.
47+
video.preload = "auto";
48+
video.src = getVideoURI(src);
49+
50+
// Prevent WebKit from garbage collecting event handlers.
51+
window._video = video;
52+
});
53+
}
54+
}
55+
56+
function makeVideo() {
57+
return makeMakeVideo("../../../../../images/pattern")();
58+
}
59+
60+
var imageBitmapDataUrlVideoPromise = self.GLOBAL && self.GLOBAL.isWorker()
61+
// /common/media.js can't load in a Worker so we don't have getVideoURI
62+
? null
63+
: fetch(getVideoURI("../../../../../images/pattern"))
64+
.then(response => Promise.all([response.headers.get("Content-Type"), response.arrayBuffer()]))
65+
.then(([type, data]) => {
66+
return new Promise(function(resolve, reject) {
67+
var video = document.createElement("video");
68+
video.oncanplaythrough = function() {
69+
resolve(video);
70+
};
71+
video.onerror = reject;
72+
73+
var encoded = btoa(String.fromCodePoint(...new Uint8Array(data)));
74+
var dataUrl = `data:${type};base64,${encoded}`;
75+
76+
// preload=auto is required to ensure a frame is available once
77+
// canplaythrough is fired. The default of preload=metadata does not
78+
// gaurantee this.
79+
video.preload = "auto";
80+
video.src = dataUrl;
81+
82+
// Prevent WebKit from garbage collecting event handlers.
83+
window._dataVideo = video;
84+
});
85+
});
86+
87+
function makeDataUrlVideo() {
88+
return imageBitmapDataUrlVideoPromise;
89+
}
90+
91+
function makeMakeHTMLImage(src) {
92+
return function() {
93+
return new Promise((resolve, reject) => {
94+
var img = new Image();
95+
img.onload = function() {
96+
resolve(img);
97+
};
98+
img.onerror = reject;
99+
img.src = src;
100+
});
101+
}
102+
}
103+
104+
function makeMakeSVGImage(src) {
105+
return function() {
106+
return new Promise((resolve, reject) => {
107+
var image = document.createElementNS("http://www.w3.org/2000/svg", "image");
108+
image.onload = () => resolve(image);
109+
image.onerror = reject;
110+
image.setAttribute("externalResourcesRequired", "true");
111+
image.setAttributeNS("http://www.w3.org/1999/xlink", 'xlink:href', src);
112+
document.body.appendChild(image);
113+
});
114+
}
115+
}
116+
117+
function makeImageData() {
118+
return new Promise(function(resolve, reject) {
119+
var width = 20, height = 20;
120+
var imgData = new ImageData(width, height);
121+
for (var i = 0; i < width * height * 4; i += 4) {
122+
imgData.data[i] = 0;
123+
imgData.data[i + 1] = 0;
124+
imgData.data[i + 2] = 0;
125+
imgData.data[i + 3] = 255; //alpha channel: 255
126+
}
127+
var halfWidth = width / 2;
128+
var halfHeight = height / 2;
129+
// initialize to R, G, B, Black, with each one 10*10 pixels
130+
for (var i = 0; i < halfHeight; i++)
131+
for (var j = 0; j < halfWidth; j++)
132+
imgData.data[i * width * 4 + j * 4] = 255;
133+
for (var i = 0; i < halfHeight; i++)
134+
for (var j = halfWidth; j < width; j++)
135+
imgData.data[i * width * 4 + j * 4 + 1] = 255;
136+
for (var i = halfHeight; i < height; i++)
137+
for (var j = 0; j < halfWidth; j++)
138+
imgData.data[i * width * 4 + j * 4 + 2] = 255;
139+
resolve(imgData);
140+
});
141+
}
142+
143+
function makeImageBitmap() {
144+
return makeCanvas().then(canvas => {
145+
return createImageBitmap(canvas);
146+
});
147+
}
148+
149+
function makeBlob(src) {
150+
return function () {
151+
return new Promise(function(resolve, reject) {
152+
var xhr = new XMLHttpRequest();
153+
xhr.open("GET", src);
154+
xhr.responseType = 'blob';
155+
xhr.send();
156+
xhr.onload = function() {
157+
resolve(xhr.response);
158+
};
159+
});
160+
}
161+
}
162+
163+
var imageSourceTypes = [
164+
{ name: 'an HTMLCanvasElement', factory: makeCanvas },
165+
{ name: 'an HTMLVideoElement', factory: makeVideo },
166+
{ name: 'an HTMLVideoElement from a data URL', factory: makeDataUrlVideo },
167+
{ name: 'a bitmap HTMLImageElement', factory: makeMakeHTMLImage("../../../../../images/pattern.png") },
168+
{ name: 'a vector HTMLImageElement', factory: makeMakeHTMLImage("../../../../../images/pattern.svg") },
169+
{ name: 'a bitmap SVGImageElement', factory: makeMakeSVGImage("../../../../../images/pattern.png") },
170+
{ name: 'a vector SVGImageElement', factory: makeMakeSVGImage("../../../../../images/pattern.svg") },
171+
{ name: 'an OffscreenCanvas', factory: makeOffscreenCanvas },
172+
{ name: 'an ImageData', factory: makeImageData },
173+
{ name: 'an ImageBitmap', factory: makeImageBitmap },
174+
{ name: 'a Blob', factory: makeBlob("../../../../../images/pattern.png") },
175+
];

0 commit comments

Comments
 (0)