hkjiang26 opened a new issue, #2563:
URL: https://github.com/apache/age/issues/2563

   **AGE Version:** apache/age master @ cfd3b634 (2026-08-14), extension 1.8.0, 
on PostgreSQL 18.6
   
   **Installation Method:** Docker
   
   **API:** SQL (psql)
   
   ### Steps to reproduce
   
   1. On a fresh database, run (no data required):
   
   ```sql
   LOAD 'age';
   SET search_path = ag_catalog, public;
   SELECT ag_catalog.age_tobooleanlist('[true]');
   ```
   
   All four `age_to*list` functions crash deterministically on array-shaped 
literal arguments (12 shapes verified):
   
   | Statement | Result |
   |---|---|
   | `age_tobooleanlist('[true]')`, `('[null]')`, `('[true, null, false]')` | 
SIGSEGV |
   | `age_tofloatlist('[true]')`, `('[1]')`, `('[null]')` | SIGSEGV |
   | `age_tointegerlist('[true]')`, `('[null]')` | SIGSEGV |
   | `age_tostringlist('[true]')`, `('[null]')`, `('[1, null, "a"]')` | SIGSEGV 
|
   
   Other array shapes (`'[1]'`, `'["a"]'`, `'[1.5]'` for the mismatched 
functions) give a bogus `ERROR: toBooleanList() argument must resolve to a list 
or null` instead — same root cause, non-crashing bit pattern.
   
   ### Expected behavior
   
   The Cypher equivalents work correctly and define the expected behavior:
   
   ```sql
   SELECT * FROM cypher('g', $$ RETURN toBooleanList([true]) $$) AS (r agtype);
   -- r = [true]
   ```
   
   The SQL form should either return the same result or raise a clean error; it 
must never crash the backend.
   
   ### Actual behavior
   
   ```
   psql: server closed the connection unexpectedly
           This probably means the server terminated abnormally
           before or while processing the request.
   psql: error: connection to server was lost
   ```
   
   Server log (docker logs):
   
   ```
   LOG:  client backend (PID 14030) was terminated by signal 11: Segmentation 
fault
   LOG:  all server processes terminated; reinitializing
   ```
   
   Root cause (in `src/backend/utils/adt/agtype.c`): type confusion at the SQL 
boundary. For `VARIADIC "any"` functions, PostgreSQL resolves an unknown-type 
literal to `text` (verified with the same-signature builtin 
`json_build_array('[true]')` → `["[true]"]`), i.e. the function receives a 
`text[]` (ArrayType) datum, not agtype. The C functions read the argument with 
`AG_GET_ARG_AGTYPE_P(0)` without ever checking `get_fn_expr_argtype()`, so the 
`text[]` datum is reinterpreted as an agtype container. Depending on the 
literal's byte pattern the garbage either passes the `AGT_ROOT_IS_ARRAY` root 
check and crashes while iterating elements (the 12 shapes above), or fails it 
and produces the bogus `argument must resolve to a list or null` error 
(`'[1]'`, `'["a"]'`, `'[1.5]'`). Passing an explicit `::agtype` cast works 
correctly — `age_tobooleanlist('[true]'::agtype)` returns `[true]` — and the 
explicit `VARIADIC ARRAY[...]` form hits the same reinterpretation. `EXPLAIN 
(VERBOSE)` of
  a crashing call also crashes the backend.
   
   Cypher is safe: literal lists are built through `agtype_build_list` (null 
elements get real value slots) and the transform passes a typed agtype 
expression, so the C code never sees a text[]; the PREPARE/EXECUTE parameter 
path was verified safe as well. Trigger surface = AGE's public SQL API 
(shared-instance DoS, same class as the `?` crash).
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to