glslang icon indicating copy to clipboard operation
glslang copied to clipboard

No upper bound on array sizes leads to resource exhaustion

Open johnstiles-google opened this issue 3 years ago • 0 comments

Our team recently found a case (indirectly, via fuzzing) where simple code could lead to timeout during compilation. The issue is that glslang sets no upper bound on the size of an array, and basic operations like = or == generate an unrolled loop of the array length. So simply copying an array or comparing two arrays can quickly emit millions and millions of instructions:

#version 460
layout (location = 0) out vec4 fragColor;
void main()
{
    int a[10000000], b[10000000];
    a==b;
    fragColor = vec4(0.4, 0.4, 0.8, 1.0);
}

This generates over 40,000,000 instructions and takes 15+ seconds to compile. The finished program contains the same four-instruction "extract/compare/logical-and" sequence 10,000,000 times:

        39999995:      6(int) CompositeExtract 12 9999995
        39999996:      6(int) CompositeExtract 14 9999995
        39999997:    15(bool) IEqual 39999995 39999996
        39999998:    15(bool) LogicalAnd 39999994 39999997
        39999999:      6(int) CompositeExtract 12 9999996
        40000000:      6(int) CompositeExtract 14 9999996
        40000001:    15(bool) IEqual 39999999 40000000
        40000002:    15(bool) LogicalAnd 39999998 40000001
        40000003:      6(int) CompositeExtract 12 9999997
        40000004:      6(int) CompositeExtract 14 9999997
        40000005:    15(bool) IEqual 40000003 40000004
        40000006:    15(bool) LogicalAnd 40000002 40000005
        40000007:      6(int) CompositeExtract 12 9999998
        40000008:      6(int) CompositeExtract 14 9999998
        40000009:    15(bool) IEqual 40000007 40000008
        40000010:    15(bool) LogicalAnd 40000006 40000009
        40000011:      6(int) CompositeExtract 12 9999999
        40000012:      6(int) CompositeExtract 14 9999999
        40000013:    15(bool) IEqual 40000011 40000012
        40000014:    15(bool) LogicalAnd 40000010 40000013
                              Store 40000018(fragColor) 40000022
                              Return
                              FunctionEnd

Our fuzzer just made lots of large arrays and copied/compared them repeatedly to burn through all the time allotted to glslang, and declared that it had found a timeout.

This could be averted by setting an arbitrary upper bound on array length, or using a loop for large arrays.

johnstiles-google avatar Oct 25 '21 14:10 johnstiles-google