Skip to content

Commit ae3d40b

Browse files
committed
Avoid direct C access to possibly-null pg_subscription_rel.srsublsn.
This coding technique is unsafe, since we'd be accessing off the end of the tuple if the field is null. SIGSEGV is pretty improbable, but perhaps not impossible. Also, returning garbage for the LSN doesn't seem like a great idea, even if callers aren't looking at it today. Also update docs to point out explicitly that pg_subscription.subslotname and pg_subscription_rel.srsublsn can be null. Perhaps we should mark these two fields BKI_FORCE_NULL, so that they'd be correctly labeled in databases that are initdb'd in the future. But we can't force that for existing databases, and on balance it's not too clear that having a mix of different catalog contents in the field would be wise. Apply to v10 (where this code came in) through v12. Already fixed in v13 and HEAD. Discussion: https://postgr.es/m/732838.1595278439@sss.pgh.pa.us
1 parent 39d6aec commit ae3d40b

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6578,8 +6578,9 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</>:<replaceable>&lt;salt&gt;<
65786578
<entry><structfield>subslotname</structfield></entry>
65796579
<entry><type>name</type></entry>
65806580
<entry></entry>
6581-
<entry>Name of the replication slot in the upstream database. Also used
6582-
for local replication origin name.</entry>
6581+
<entry>Name of the replication slot in the upstream database (also used
6582+
for the local replication origin name);
6583+
null represents <literal>NONE</literal></entry>
65836584
</row>
65846585

65856586
<row>
@@ -6661,7 +6662,9 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</>:<replaceable>&lt;salt&gt;<
66616662
<entry><type>pg_lsn</type></entry>
66626663
<entry></entry>
66636664
<entry>
6664-
End LSN for <literal>s</> and <literal>r</> states.
6665+
Remote LSN of the state change used for synchronization coordination
6666+
when in <literal>s</literal> or <literal>r</literal> states,
6667+
otherwise null
66656668
</entry>
66666669
</row>
66676670
</tbody>

src/backend/catalog/pg_subscription.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,13 +442,20 @@ GetSubscriptionRelations(Oid subid)
442442
{
443443
Form_pg_subscription_rel subrel;
444444
SubscriptionRelState *relstate;
445+
Datum d;
446+
bool isnull;
445447

446448
subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
447449

448450
relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
449451
relstate->relid = subrel->srrelid;
450452
relstate->state = subrel->srsubstate;
451-
relstate->lsn = subrel->srsublsn;
453+
d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
454+
Anum_pg_subscription_rel_srsublsn, &isnull);
455+
if (isnull)
456+
relstate->lsn = InvalidXLogRecPtr;
457+
else
458+
relstate->lsn = DatumGetLSN(d);
452459

453460
res = lappend(res, relstate);
454461
}
@@ -494,13 +501,20 @@ GetSubscriptionNotReadyRelations(Oid subid)
494501
{
495502
Form_pg_subscription_rel subrel;
496503
SubscriptionRelState *relstate;
504+
Datum d;
505+
bool isnull;
497506

498507
subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
499508

500509
relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
501510
relstate->relid = subrel->srrelid;
502511
relstate->state = subrel->srsubstate;
503-
relstate->lsn = subrel->srsublsn;
512+
d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
513+
Anum_pg_subscription_rel_srsublsn, &isnull);
514+
if (isnull)
515+
relstate->lsn = InvalidXLogRecPtr;
516+
else
517+
relstate->lsn = DatumGetLSN(d);
504518

505519
res = lappend(res, relstate);
506520
}

src/include/catalog/pg_subscription_rel.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,17 @@ CATALOG(pg_subscription_rel,6102) BKI_WITHOUT_OIDS
3131
Oid srsubid; /* Oid of subscription */
3232
Oid srrelid; /* Oid of relation */
3333
char srsubstate; /* state of the relation in subscription */
34-
pg_lsn srsublsn; /* remote lsn of the state change used for
35-
* synchronization coordination */
34+
35+
/*
36+
* Although srsublsn is a fixed-width type, it is allowed to be NULL, so
37+
* we prevent direct C code access to it just as for a varlena field.
38+
*/
39+
#ifdef CATALOG_VARLEN /* variable-length fields start here */
40+
41+
pg_lsn srsublsn; /* remote LSN of the state change used for
42+
* synchronization coordination, or NULL if
43+
* not valid */
44+
#endif
3645
} FormData_pg_subscription_rel;
3746

3847
typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;

0 commit comments

Comments
 (0)