mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_Test/Program): add test for malicious shader using sampler as variable name
This commit is contained in:
@@ -997,3 +997,220 @@ TEST_F(ProgramTest, CompileAndLinkWithExplicitFragmentOut) {
|
||||
ASSERT_TRUE(pSrcfragOut != nullptr) << "Not found expected string in generated shader.\n(Searching for \"" << needle
|
||||
<< "\")";
|
||||
}
|
||||
|
||||
const char* vs_sampler_as_varname = R"(#version 330
|
||||
in vec3 Position;
|
||||
out float sphericalVertexDistance;
|
||||
out float cylindricalVertexDistance;
|
||||
out vec4 vertexColor;
|
||||
out vec2 texCoord0;
|
||||
void main() {
|
||||
gl_Position = vec4(Position, 1.0);
|
||||
sphericalVertexDistance = 1.0;
|
||||
cylindricalVertexDistance = 1.0;
|
||||
vertexColor = vec4(Position, 1.0);
|
||||
texCoord0 = Position.xy;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* fs_sampler_as_varname = R"(#version 330
|
||||
|
||||
layout(std140) uniform Fog {
|
||||
vec4 FogColor;
|
||||
float FogEnvironmentalStart;
|
||||
float FogEnvironmentalEnd;
|
||||
float FogRenderDistanceStart;
|
||||
float FogRenderDistanceEnd;
|
||||
float FogSkyEnd;
|
||||
float FogCloudsEnd;
|
||||
};
|
||||
|
||||
float linear_fog_value(float vertexDistance, float fogStart, float fogEnd) {
|
||||
if (vertexDistance <= fogStart) {
|
||||
return 0.0;
|
||||
} else if (vertexDistance >= fogEnd) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return (vertexDistance - fogStart) / (fogEnd - fogStart);
|
||||
}
|
||||
|
||||
float total_fog_value(float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd) {
|
||||
return max(linear_fog_value(sphericalVertexDistance, environmentalStart, environmantalEnd), linear_fog_value(cylindricalVertexDistance, renderDistanceStart, renderDistanceEnd));
|
||||
}
|
||||
|
||||
vec4 apply_fog(vec4 inColor, float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd, vec4 fogColor) {
|
||||
float fogValue = total_fog_value(sphericalVertexDistance, cylindricalVertexDistance, environmentalStart, environmantalEnd, renderDistanceStart, renderDistanceEnd);
|
||||
return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
|
||||
}
|
||||
|
||||
float fog_spherical_distance(vec3 pos) {
|
||||
return length(pos);
|
||||
}
|
||||
|
||||
float fog_cylindrical_distance(vec3 pos) {
|
||||
float distXZ = length(pos.xz);
|
||||
float distY = abs(pos.y);
|
||||
return max(distXZ, distY);
|
||||
}
|
||||
|
||||
|
||||
layout(std140) uniform Globals {
|
||||
ivec3 CameraBlockPos;
|
||||
vec3 CameraOffset;
|
||||
vec2 ScreenSize;
|
||||
float GlintAlpha;
|
||||
float GameTime;
|
||||
int MenuBlurRadius;
|
||||
int UseRgss;
|
||||
};
|
||||
|
||||
|
||||
layout(std140) uniform ChunkSection {
|
||||
mat4 ModelViewMat;
|
||||
float ChunkVisibility;
|
||||
ivec2 TextureSize;
|
||||
ivec3 ChunkPosition;
|
||||
};
|
||||
|
||||
uniform sampler2D Sampler0;
|
||||
|
||||
in float sphericalVertexDistance;
|
||||
in float cylindricalVertexDistance;
|
||||
in vec4 vertexColor;
|
||||
in vec2 texCoord0;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 sampleNearest(sampler2D sampler, vec2 uv, vec2 pixelSize, vec2 du, vec2 dv, vec2 texelScreenSize) {
|
||||
// Convert our UV back up to texel coordinates and find out how far over we are from the center of each pixel
|
||||
vec2 uvTexelCoords = uv / pixelSize;
|
||||
vec2 texelCenter = round(uvTexelCoords) - 0.5f;
|
||||
vec2 texelOffset = uvTexelCoords - texelCenter;
|
||||
|
||||
// Move our offset closer to the texel center based on texel size on screen
|
||||
texelOffset = (texelOffset - 0.5f) * pixelSize / texelScreenSize + 0.5f;
|
||||
texelOffset = clamp(texelOffset, 0.0f, 1.0f);
|
||||
|
||||
uv = (texelCenter + texelOffset) * pixelSize;
|
||||
return textureGrad(sampler, uv, du, dv);
|
||||
}
|
||||
|
||||
vec4 sampleNearest(sampler2D source, vec2 uv, vec2 pixelSize) {
|
||||
vec2 du = dFdx(uv);
|
||||
vec2 dv = dFdy(uv);
|
||||
vec2 texelScreenSize = sqrt(du * du + dv * dv);
|
||||
return sampleNearest(source, uv, pixelSize, du, dv, texelScreenSize);
|
||||
}
|
||||
|
||||
// Rotated Grid Super-Sampling
|
||||
vec4 sampleRGSS(sampler2D source, vec2 uv, vec2 pixelSize) {
|
||||
vec2 du = dFdx(uv);
|
||||
vec2 dv = dFdy(uv);
|
||||
|
||||
vec2 texelScreenSize = sqrt(du * du + dv * dv);
|
||||
float maxTexelSize = max(texelScreenSize.x, texelScreenSize.y);
|
||||
|
||||
float minPixelSize = min(pixelSize.x, pixelSize.y);
|
||||
|
||||
float transitionStart = minPixelSize * 1.0;
|
||||
float transitionEnd = minPixelSize * 2.0;
|
||||
float blendFactor = smoothstep(transitionStart, transitionEnd, maxTexelSize);
|
||||
|
||||
float duLength = length(du);
|
||||
float dvLength = length(dv);
|
||||
float minDerivative = min(duLength, dvLength);
|
||||
float maxDerivative = max(duLength, dvLength);
|
||||
|
||||
float effectiveDerivative = sqrt(minDerivative * maxDerivative);
|
||||
|
||||
float mipLevelExact = max(0.0, log2(effectiveDerivative / minPixelSize));
|
||||
|
||||
float mipLevelLow = floor(mipLevelExact);
|
||||
float mipLevelHigh = mipLevelLow + 1.0;
|
||||
float mipBlend = fract(mipLevelExact);
|
||||
|
||||
const vec2 offsets[4] = vec2[](
|
||||
vec2(0.125, 0.375),
|
||||
vec2(-0.125, -0.375),
|
||||
vec2(0.375, -0.125),
|
||||
vec2(-0.375, 0.125)
|
||||
);
|
||||
|
||||
vec4 rgssColorLow = vec4(0.0);
|
||||
vec4 rgssColorHigh = vec4(0.0);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
vec2 sampleUV = uv + offsets[i] * pixelSize;
|
||||
rgssColorLow += textureLod(source, sampleUV, mipLevelLow);
|
||||
rgssColorHigh += textureLod(source, sampleUV, mipLevelHigh);
|
||||
}
|
||||
rgssColorLow *= 0.25;
|
||||
rgssColorHigh *= 0.25;
|
||||
|
||||
vec4 rgssColor = mix(rgssColorLow, rgssColorHigh, mipBlend);
|
||||
|
||||
vec4 nearestColor = sampleNearest(source, uv, pixelSize, du, dv, texelScreenSize);
|
||||
|
||||
return mix(nearestColor, rgssColor, blendFactor);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = (UseRgss == 1 ? sampleRGSS(Sampler0, texCoord0, 1.0f / TextureSize) : sampleNearest(Sampler0, texCoord0, 1.0f / TextureSize)) * vertexColor;
|
||||
color = mix(FogColor * vec4(1, 1, 1, color.a), color, ChunkVisibility);
|
||||
#ifdef ALPHA_CUTOUT
|
||||
if (color.a < ALPHA_CUTOUT) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor);
|
||||
})";
|
||||
|
||||
TEST_F(ProgramTest, CompileShaderWithSamplerAsVarName) {
|
||||
char infoLog[1024] = "";
|
||||
|
||||
GLuint fs = CreateShader(GL_FRAGMENT_SHADER);
|
||||
ShaderSource(fs, 1, &fs_sampler_as_varname, NULL);
|
||||
CompileShader(fs);
|
||||
GLint fsStatus = GL_FALSE;
|
||||
GetShaderiv(fs, GL_COMPILE_STATUS, &fsStatus);
|
||||
GetShaderInfoLog(fs, 1024, nullptr, infoLog);
|
||||
ASSERT_EQ(fsStatus, GL_TRUE) << infoLog;
|
||||
|
||||
GLuint vs = CreateShader(GL_VERTEX_SHADER);
|
||||
ShaderSource(vs, 1, &vs_sampler_as_varname, NULL);
|
||||
CompileShader(vs);
|
||||
GLint vsStatus = GL_FALSE;
|
||||
GetShaderiv(vs, GL_COMPILE_STATUS, &vsStatus);
|
||||
GetShaderInfoLog(vs, 1024, nullptr, infoLog);
|
||||
ASSERT_EQ(vsStatus, GL_TRUE) << infoLog;
|
||||
|
||||
GLuint program = CreateProgram();
|
||||
AttachShader(program, fs);
|
||||
AttachShader(program, vs);
|
||||
|
||||
LinkProgram(program);
|
||||
GLint linkStatus = GL_FALSE;
|
||||
GetProgramiv(program, GL_LINK_STATUS, &linkStatus);
|
||||
ASSERT_EQ(linkStatus, GL_TRUE);
|
||||
printf("Program linked.\n");
|
||||
|
||||
UseProgram(program);
|
||||
|
||||
auto programObject = MG_State::pGLContext->GetCurrentProgram();
|
||||
auto& spirvs = programObject->GetGeneratedSpirv();
|
||||
auto& fragSpirv = spirvs[0]; // 0 - fragment, 1 - vertex
|
||||
char* pSrcfragOut = nullptr;
|
||||
MG_Util::ShaderTranspiler::SpvcSession spvcSession(fragSpirv);
|
||||
spvc_compiler_options options;
|
||||
spvcSession.CreateOptions(&options);
|
||||
|
||||
spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 460);
|
||||
spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_TRUE);
|
||||
// spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, SPVC_FALSE);
|
||||
|
||||
spvcSession.SetOptions(options);
|
||||
|
||||
const char* result = nullptr;
|
||||
spvcSession.Compile(&result);
|
||||
printf("%s\n\n", result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user