pg_get_database_ddl_internal() can dereference a NULL pointer when pg_database.dattablespace points to a tablespace OID that no longer exists.
The immediate issue is that get_tablespace_name() may return NULL, but the result is passed directly to pg_strcasecmp():
spcname = get_tablespace_name(dbform->dattablespace); if (pg_strcasecmp(spcname, "pg_default") != 0) ...
That leads to a backend crash. I reproduced it on current master as a SIGSEGV with crash recovery.
This function was introduced by commit a4f774cf1c7.
Deterministic reproduction:
CREATE DATABASE regression_testdb; SET allow_system_table_mods = on; UPDATE pg_database SET dattablespace = 99999 WHERE datname = 'regression_testdb'; RESET allow_system_table_mods;
SELECT * FROM pg_get_database_ddl('regression_testdb');
The attached patch fixes this by checking for NULL before calling pg_strcasecmp(). In that case, pg_get_database_ddl() simply omits the TABLESPACE clause.
I also added a regression test in database_ddl.sql that exercises this case by setting dattablespace to a non-existent OID and verifying that the function returns successfully.
Patch attached. Please review and let me know if it needs any edits. Thanks!