diff --git a/Cargo.toml b/Cargo.toml index d1f3b2a2..e3034db1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pgmq" -version = "0.12.0" +version = "0.12.1" edition = "2021" authors = ["Tembo.io"] description = "Postgres extension for PGMQ" diff --git a/core/Cargo.toml b/core/Cargo.toml index 8bb88798..051a9e15 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pgmq" -version = "0.15.0" +version = "0.15.1" edition = "2021" authors = ["Tembo.io"] description = "A distributed message queue for Rust applications, on Postgres." diff --git a/core/src/query.rs b/core/src/query.rs index f6b5c912..205d764b 100644 --- a/core/src/query.rs +++ b/core/src/query.rs @@ -299,10 +299,23 @@ pub fn pop(name: &str) -> Result { /// panics if input is invalid. otherwise does nothing. pub fn check_input(input: &str) -> Result<(), PgmqError> { - let valid = input + // Docs: + // https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS + + // Default value of `NAMEDATALEN`, set in `src/include/pg_config_manual.h` + const NAMEDATALEN: usize = 64; + // The maximum length of an identifier. + // Longer names can be used in commands, but they'll be truncated + const MAX_IDENTIFIER_LEN: usize = NAMEDATALEN - 1; + // The max length of a PGMQ table, considering its prefix and the underline after it (e.g. "pgmq_") + const MAX_PGMQ_TABLE_LEN: usize = MAX_IDENTIFIER_LEN - TABLE_PREFIX.len() - 1; + + let is_short_enough = input.len() <= MAX_PGMQ_TABLE_LEN; + let has_valid_characters = input .as_bytes() .iter() .all(|&c| c.is_ascii_alphanumeric() || c == b'_'); + let valid = is_short_enough && has_valid_characters; match valid { true => Ok(()), false => Err(PgmqError::InvalidQueueName { @@ -373,6 +386,18 @@ mod tests { } } + #[test] + fn check_input_rejects_names_too_large() { + let table_name = "my_valid_table_name"; + assert!(check_input(table_name).is_ok()); + + assert!(check_input(&"a".repeat(58)).is_ok()); + + assert!(check_input(&"a".repeat(59)).is_err()); + assert!(check_input(&"a".repeat(60)).is_err()); + assert!(check_input(&"a".repeat(70)).is_err()); + } + #[test] fn test_check_input() { let invalids = vec!["bad;queue_name", "bad name", "bad--name"];