From 940e7810916961aa332b607899ee05d1df238877 Mon Sep 17 00:00:00 2001 From: SAY-5 Date: Sun, 19 Apr 2026 23:14:27 -0700 Subject: [PATCH] agtype: fix substring() backend crash when start-offset is SQL NULL and length is supplied age_substring() reads the null map produced by extract_variadic_args() and rejects null offset/length with this guard: if ((nargs == 2 && nulls[1]) || (nargs == 3 && nulls[2])) { ereport(ERROR, ..., errmsg("substring() offset or length cannot be null")); } The condition only checks nulls[1] in the 2-argument form. When the caller passes `substring(str, null, len)` the function takes nargs = 3, nulls[1] = true, but the guard above does not fire. Execution reaches the numeric-parameter loop below, which reads args[1] through DatumGetInt32 / DATUM_GET_AGTYPE_P without ever re-checking nulls[i]. The Datum in that slot is undefined, the dereference segfaults, and the PostgreSQL backend terminates - not a query error but a connection-level crash (#2386). Widen the guard to nargs >= 2 && nulls[1] so it catches start-is-null in both the 2-arg and 3-arg forms. nulls[2] is still only checked when nargs == 3. No behaviour change on any non-null path; the connection-crash case is now reported as a normal query error, matching the intent the existing error message already implies. Fixes #2386 --- src/backend/utils/adt/agtype.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c index 386219556..b2215d016 100644 --- a/src/backend/utils/adt/agtype.c +++ b/src/backend/utils/adt/agtype.c @@ -8639,8 +8639,15 @@ Datum age_substring(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - /* neither offset or length can be null if there is a valid string */ - if ((nargs == 2 && nulls[1]) || + /* + * neither offset nor length may be null when there is a valid string. + * Both arg positions must be checked whenever they are supplied; the + * previous condition missed the `start is null, length is provided` + * case (nargs == 3 && nulls[1]), which fell through to the numeric + * parser below and dereferenced an undefined Datum - crashing the + * backend (#2386). + */ + if ((nargs >= 2 && nulls[1]) || (nargs == 3 && nulls[2])) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),