Skip to content

Commit

Permalink
Fix issue #1032 (#1033)
Browse files Browse the repository at this point in the history
Blindly use the `FMGR_ABI_EXTRA` constant as part of the magic block.
Hardcoding to "PostgreSQL" isn't exactly correct when using bindings
from, for example, a Postgres fork that has purposely changed its ABI
"name".

* On pg15, detect if we're being compiled against something with a different ABI than "PostgreSQL" and fail to compile.  Unless the `--unsafe-postgres` feature flag is present

Co-authored-by: Smittyvb <[email protected]>
  • Loading branch information
eeeebbbbrrrr and syvb authored Feb 16, 2023
1 parent 05d8b35 commit f18de7f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,26 @@ this feature is now considered deprecated in favor of a lower-overhead interop.
You may still request implementations of `TryFrom<time::Type> for pgx::MatchingType`
and `From<time::Type> for pgx::MatchingType` by enabling the `"time-crate"` feature.

### "unsafe-postgres": Allow compilation for Postgres forks that have a different ABI

As of Postgres v15, forks are allowed to specify they use a different ABI than canonical Postgres.
Since pgx makes countless assumptions about Postgres' internal ABI it is not possible for it to
guarantee that a compiled pgx extension will probably execute within such a Postgres fork. You,
dear compiler runner, can make this guarantee for yourself by specifying the `unsafe-postgres`
feature flag. Otherwise, a pgx extension will fail to compile with an error similar to:

```
error[E0080]: evaluation of constant value failed
--> pgx/src/lib.rs:151:5
|
151 | / assert!(
152 | | same_slice(pg_sys::FMGR_ABI_EXTRA, b"xPostgreSQL\0"),
153 | | "Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?",
154 | | );
| |_____^ the evaluated program panicked at 'Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?', pgx/src/lib.rs:151:5
|
```

### Experimental Features

Adding `pgx = { version = "0.5.0", features = ["postgrestd"] }` to your Cargo.toml
Expand Down
1 change: 1 addition & 0 deletions pgx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pg14 = [ "pgx-pg-sys/pg14" ]
pg15 = [ "pgx-pg-sys/pg15" ]
time-crate = ["dep:time"]
no-schema-generation = ["pgx-macros/no-schema-generation", "pgx-sql-entity-graph/no-schema-generation"]
unsafe-postgres = [] # when trying to compile against something that looks like Postgres but claims to be diffent

[package.metadata.docs.rs]
features = ["pg14", "cshim"]
Expand Down
32 changes: 30 additions & 2 deletions pgx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ pub use pg_sys::{
#[doc(hidden)]
pub use pgx_sql_entity_graph;

// Postgres v15 has the concept of an ABI "name". The default is `b"PostgreSQL\0"` and this is the
// ABI that pgx extensions expect to be running under. We will refuse to compile if it is detected
// that we're trying to be built against some other kind of "postgres" that has its own ABI name.
//
// Unless the compiling user explicitly told us that they're aware of this via `--features unsafe-postgres`.
#[cfg(all(feature = "pg15", not(feature = "unsafe-postgres")))]
const _: () = {
// to appease `const`
const fn same_slice(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}
assert!(
same_slice(pg_sys::FMGR_ABI_EXTRA, b"PostgreSQL\0"),
"Unsupported Postgres ABI. Perhaps you need `--features unsafe-postgres`?",
);
};

/// A macro for marking a library compatible with [`pgx`][crate].
///
/// <div class="example-wrap" style="display:inline-block">
Expand Down Expand Up @@ -220,8 +247,9 @@ macro_rules! pg_magic_func {
namedatalen: pgx::pg_sys::NAMEDATALEN as i32,
float8byval: cfg!(target_pointer_width = "64") as i32,
abi_extra: {
// array::from_fn isn't const yet, boohoo, so const-copy a bstr
let magic = b"PostgreSQL";
// we'll use what the bindings tell us, but if it ain't "PostgreSQL" then we'll
// raise a compilation error unless the `unsafe-postgres` feature is set
let magic = pgx::pg_sys::FMGR_ABI_EXTRA;
let mut abi = [0 as ::pgx::ffi::c_char; 32];
let mut i = 0;
while i < magic.len() {
Expand Down

0 comments on commit f18de7f

Please sign in to comment.