Shader array property causing weirdness with UI masks

I have a shader that is fed an array of colors from script, and everything worked great until I had masks on 2 overlapping canvases. The mask in the behind canvas causes the masked image in the front canvas to show if they overlap. After much hair-pulling, I finally narrowed down the issue to array access, which still makes no sense to me. Is there any solution to this?

Here is the stripped shader code that still exerts this behavior:

Shader "Custom/Color Shift"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}

        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
        _ColorMask ("Color Mask", Float) = 15
        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
    
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend SrcAlpha OneMinusSrcAlpha
        ColorMask [_ColorMask]
        Pass
        {
            Name "Default"
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #include "UnityCG.cginc"
            #include "UnityUI.cginc"
            #pragma multi_compile __ UNITY_UI_ALPHACLIP
        
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
            };
        
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;
            float _Stencil;
            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.worldPosition = IN.vertex;
                OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
                OUT.texcoord = IN.texcoord;
            
                OUT.color = IN.color;
                return OUT;
            }
            sampler2D _MainTex;

            fixed4 _Colors[16];
            int _ColorCount; // Min 1 max 16
            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
               
                color *= _Colors[0]; // Removing this works as expected.
               
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                clip (color.a - 0.001);
                return color;
            }
        ENDCG
        }
    }
}

Well, I still have no idea why this works this way, but I managed to hack around it by passing my data in a texture instead of an array, and then adding that texture into the shader’s Properties section (seems properties have to be in that section to work with masks, and we can’t put arrays in there).
Then, for some reason, I still had to add this to my script when I update the material, even though I’m setting both graphic.material and graphic.materialForRendering

Mask mask = GetComponent<Mask>();
if (mask)
{
    // This is necessary for masking to work properly, for some reason...
    mask.enabled = false;
    mask.enabled = true;
}