NotHimmel opened a new pull request, #2521:
URL: https://github.com/apache/age/pull/2521

   Fixes #2519
   
   ### Problem
   
   `node_label` is declared `name = NULL` in the SQL signature of
   `ag_catalog.age_create_barbell_graph()`, so leaving it out — or passing 
`NULL`
   explicitly — is a supported call. Both crashed the backend with SIGSEGV, 
which
   makes the postmaster reinitialize and drops every other session on the
   instance.
   
   ```sql
   SELECT create_graph('barbell_test');
   SELECT age_create_barbell_graph('barbell_test', 5, 0);
   -- server closed the connection unexpectedly
   ```
   
   ```
   LOG:  client backend (PID 312566) was terminated by signal 11: Segmentation 
fault
   LOG:  all server processes terminated; reinitializing
   ```
   
   ### Root cause
   
   There are two separate faults on the null-`node_label` path.
   
   **1. The default label was copied into a null pointer.**
   
   ```c
   Name node_label_name = NULL;
   ...
   if (PG_ARGISNULL(3))
       namestrcpy(node_label_name, AG_DEFAULT_LABEL_VERTEX);
   ```
   
   `namestrcpy()` writes through the pointer it is given and does not allocate, 
so
   this writes to address 0. The fix gives the default its own `NameData`. As a
   side effect the default now actually takes effect, which it never did.
   
   Note that the immediate segfault only happens on PostgreSQL 14 and later.
   `namestrcpy()` used to start with `if (!name || !str) return -1;`, removed by
   PostgreSQL commit `1784f278a638` ("Replace remaining StrNCpy() by strlcpy()",
   first released in 14). On PG 13 and earlier the call silently did nothing, so
   `node_label_str` simply ended up NULL and the failure moved downstream.
   
   **2. The node label was forwarded as the raw argument Datum.**
   
   ```c
   DirectFunctionCall4(create_complete_graph, ..., arguments->args[3].value);
   ```
   
   `DirectFunctionCall4()` marks every argument as not null, so a null node 
label
   reached `create_complete_graph()` as a non-null NULL pointer and was
   dereferenced by its vertex/edge label comparison. Fixing only the 
`namestrcpy()`
   call is therefore not enough — verified: with just that change,
   `age_create_barbell_graph('g', 5, 0, NULL, NULL, 'E')` still segfaults. The
   resolved label is forwarded instead.
   
   `create_complete_graph()` already handles its own null node label correctly;
   this change makes the barbell function follow the same approach.
   
   ### How the bug was introduced
   
   By the original barbell implementation, `0c79370` ("Barbell graph 
generation",
   #648, 2023-02-17). Present on `master`, `PG16`, `PG17`, `PG18` and `PG19`, so
   the fix likely wants backporting to those branches.
   
   ### Testing
   
   Extended `regress/sql/graph_generation.sql` with the previously untested 
cases.
   The existing barbell tests always passed a node label, except for the
   all-arguments-null case, which errors out on the graph name before ever
   reaching this code — which is why this was never caught.
   
   ```sql
   SELECT * FROM age_create_barbell_graph('gp7',5,0,NULL,NULL,'edges',NULL);
   SELECT COUNT(*) FROM gp7."_ag_label_vertex";
   SELECT COUNT(*) FROM gp7."edges";
   SELECT * FROM cypher('gp7', $$MATCH (a)-[e]->(b) RETURN e$$) as (n agtype);
   
   -- SHOULD FAIL, but with an error rather than a crash
   SELECT * FROM age_create_barbell_graph('gp8',5,0);
   ```
   
   On PostgreSQL 18.4, built from source:
   
   * Without the code change, `graph_generation` fails with
     `server closed the connection unexpectedly`, and because the crash takes 
the
     temporary instance down with it, the ten tests that follow fail as well.
   * With the code change, `# All 43 tests passed.`
   
   The new cases also confirm the default label is applied: `gp7` gets 10 
vertices
   under `_ag_label_vertex` (two K5s) and 21 edges (2 × 10 plus the bridge).
   
   ### Out of scope
   
   Three other defects in the same function, left alone to keep this change
   focused. Happy to open separate issues:
   
   * `if (PG_ARGISNULL(1) && PG_GETARG_INT32(1) < 3)` should use `||`. As 
written,
     `graph_size` of 1 or 2 passes the check silently.
   * `node_properties` and `edge_properties` are accepted but ignored;
     `properties` is hardcoded to `create_empty_agtype()`.
   * `bridge_size` is validated but unused, as the in-code comment notes.
   


-- 
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