Ewan Young <[email protected]> 于2026年7月2日周四 13:43写道:
>
> Thanks for taking a look, and for confirming the non-variadic point.
>
> I think that placement doesn't quite cover it, though. There are two
> PG_GETARG_ARRAYTYPE_P(3) calls:
> the one in the cache-setup branch you patched (reached only on the
> first call, or when the parent OID changes),
> and a second one in the deconstruct_array() path that runs on every
> call. Because fn_extra is cached across calls,
> a NULL array can skip the cache-setup block and reach that second
> fetch unguarded — so it still crashes:
>
> create table hp (a int) partition by hash (a);
> create table hp0 partition of hp for values with (modulus 2, remainder 0);
> create table hp1 partition of hp for values with (modulus 2, remainder 1);
> create table t (arr int[]);
> insert into t values (array[1]), (null), (array[2]);
> select satisfies_hash_partition('hp'::regclass, 2, 0, variadic arr) from t;
>
> The first (non-NULL) row builds the cache, and the NULL row then
> crashes in the deconstruct path.
> With the top-level check it returns t/f/t. (The cache-setup placement
> also returns between relation_open()
> and relation_close(), so it trips "resource was not closed" even for
> the single-NULL case.)

Yes.  The previous fix cannot prevent a crash if my_extra is not NULL,
as your case shows
And I forgot to call relation_close(), so "resource was not closed" would occur.
Anyway, the NULL-array guard must sit ahead.

>
> You're right that the top-level version calls get_fn_expr_variadic()
> once more in the non-variadic path.
> It's just an O(1) read of the funcvariadic flag, so I left it as is —
> but if you'd rather not repeat it, we could
> compute it once into a local near the top and reuse it. Either way the
> NULL-array guard needs to sit ahead
> of both array fetches.

Personally,  I prefer a local bool variable near the top and reuse it.


-- 
Thanks,
Tender Wang


Reply via email to