Skip to content

Commit

Permalink
fix: validate integers to prevent overflow (#3231)
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Sep 26, 2022
1 parent d489390 commit 5a6e984
Show file tree
Hide file tree
Showing 22 changed files with 907 additions and 31 deletions.
14 changes: 13 additions & 1 deletion psl/builtin-connectors/src/cockroach_datamodel_connector.rs
Expand Up @@ -6,6 +6,7 @@ use native_types::{CockroachType, NativeType};
use psl_core::{
datamodel_connector::{
helper::{arg_vec_from_opt, args_vec_from_opt, parse_one_opt_u32, parse_two_opt_u32},
int_type::IntType,
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity, StringFilter,
},
Expand Down Expand Up @@ -156,7 +157,7 @@ impl Connector for CockroachDatamodelConnector {
// Int
CockroachType::Int2 => ScalarType::Int,
CockroachType::Int4 => ScalarType::Int,
CockroachType::Oid => ScalarType::Int,
CockroachType::Oid => ScalarType::Int, // Unsigned 32-bit int
// BigInt
CockroachType::Int8 => ScalarType::BigInt,
// Float
Expand Down Expand Up @@ -379,6 +380,17 @@ impl Connector for CockroachDatamodelConnector {
}
}
}

fn int_type(&self, native_type: serde_json::Value) -> Option<IntType> {
let nt: CockroachType = serde_json::from_value(native_type).unwrap();

match nt {
CockroachType::Int2 => Some(IntType::Signed16),
CockroachType::Int4 => Some(IntType::Signed32),
CockroachType::Oid => Some(IntType::Unsigned32),
_ => None,
}
}
}

/// An `@default(sequence())` function.
Expand Down
11 changes: 10 additions & 1 deletion psl/builtin-connectors/src/mongodb.rs
Expand Up @@ -6,7 +6,7 @@ use mongodb_types::*;
use native_types::{MongoDbType, NativeType};
use psl_core::{
datamodel_connector::{
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
int_type::IntType, Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity,
},
diagnostics::{DatamodelError, Diagnostics, Span},
Expand Down Expand Up @@ -132,4 +132,13 @@ impl Connector for MongoDbDatamodelConnector {
fn allowed_referential_integrity_settings(&self) -> enumflags2::BitFlags<ReferentialIntegrity> {
ReferentialIntegrity::Prisma.into()
}

fn int_type(&self, native_type: serde_json::Value) -> Option<IntType> {
let nt: MongoDbType = serde_json::from_value(native_type).unwrap();

match nt {
MongoDbType::Int => Some(IntType::Signed32),
_ => None,
}
}
}
12 changes: 12 additions & 0 deletions psl/builtin-connectors/src/mssql_datamodel_connector.rs
Expand Up @@ -8,6 +8,7 @@ use once_cell::sync::Lazy;
use psl_core::{
datamodel_connector::{
helper::{arg_vec_from_opt, args_vec_from_opt, parse_one_opt_u32, parse_two_opt_u32},
int_type::IntType,
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity,
},
Expand Down Expand Up @@ -438,6 +439,17 @@ impl Connector for MsSqlDatamodelConnector {
});
}
}

fn int_type(&self, native_type: serde_json::Value) -> Option<IntType> {
let nt: MsSqlType = serde_json::from_value(native_type).unwrap();

match nt {
TinyInt => Some(IntType::Unsigned8),
SmallInt => Some(IntType::Signed16),
Int => Some(IntType::Signed32),
_ => None,
}
}
}

/// A collection of types stored outside of the row to the heap, having
Expand Down
19 changes: 19 additions & 0 deletions psl/builtin-connectors/src/mysql_datamodel_connector.rs
Expand Up @@ -8,6 +8,7 @@ use native_types::{
use psl_core::{
datamodel_connector::{
helper::{args_vec_from_opt, parse_one_opt_u32, parse_one_u32, parse_two_opt_u32},
int_type::IntType,
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity,
},
Expand Down Expand Up @@ -405,4 +406,22 @@ impl Connector for MySqlDatamodelConnector {

Ok(())
}

fn int_type(&self, native_type: serde_json::Value) -> Option<IntType> {
let nt: MySqlType = serde_json::from_value(native_type).unwrap();

match nt {
MySqlType::TinyInt => Some(IntType::Signed8),
MySqlType::SmallInt => Some(IntType::Signed16),
MySqlType::MediumInt => Some(IntType::Signed24),
MySqlType::Int => Some(IntType::Signed32),
MySqlType::UnsignedTinyInt => Some(IntType::Unsigned8),
MySqlType::UnsignedSmallInt => Some(IntType::Unsigned16),
MySqlType::UnsignedMediumInt => Some(IntType::Unsigned24),
MySqlType::UnsignedInt => Some(IntType::Unsigned32),
// Technically stored as an Unsigned8 but with values ranging from 1901 and 2155
MySqlType::Year => Some(IntType::Custom(1901, 2155)),
_ => None,
}
}
}
13 changes: 13 additions & 0 deletions psl/builtin-connectors/src/postgres_datamodel_connector.rs
Expand Up @@ -9,6 +9,7 @@ use native_types::{
use psl_core::{
datamodel_connector::{
helper::{arg_vec_from_opt, args_vec_from_opt, parse_one_opt_u32, parse_two_opt_u32},
int_type::IntType,
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity, StringFilter,
},
Expand Down Expand Up @@ -179,6 +180,7 @@ impl Connector for PostgresDatamodelConnector {
//Int
SmallInt => ScalarType::Int,
Integer => ScalarType::Int,
// Unsigned 32-bit int
Oid => ScalarType::Int,
//BigInt
BigInt => ScalarType::BigInt,
Expand Down Expand Up @@ -452,6 +454,17 @@ impl Connector for PostgresDatamodelConnector {
_ => (),
}
}

fn int_type(&self, native_type: serde_json::Value) -> Option<IntType> {
let nt: PostgresType = serde_json::from_value(native_type).unwrap();

match nt {
SmallInt => Some(IntType::Signed16),
Integer => Some(IntType::Signed32),
Oid => Some(IntType::Unsigned32),
_ => None,
}
}
}

fn allowed_index_operator_classes(algo: IndexAlgorithm, field: walkers::ScalarFieldWalker<'_>) -> Vec<OperatorClass> {
Expand Down
6 changes: 5 additions & 1 deletion psl/builtin-connectors/src/sqlite_datamodel_connector.rs
@@ -1,7 +1,7 @@
use enumflags2::BitFlags;
use psl_core::{
datamodel_connector::{
Connector, ConnectorCapability, ConstraintScope, NativeTypeConstructor, NativeTypeInstance,
Connector, ConnectorCapability, ConstraintScope, IntType, NativeTypeConstructor, NativeTypeInstance,
ReferentialIntegrity,
},
diagnostics::{DatamodelError, Span},
Expand Down Expand Up @@ -115,4 +115,8 @@ impl Connector for SqliteDatamodelConnector {

Ok(())
}

fn int_type(&self, _native_type: serde_json::Value) -> Option<IntType> {
None
}
}
7 changes: 7 additions & 0 deletions psl/psl-core/src/datamodel_connector.rs
Expand Up @@ -6,6 +6,8 @@ pub mod capabilities;
pub mod constraint_names;
/// Helpers for implementors of `Connector`.
pub mod helper;
/// Type to represent the storage and unsignedness of an integer type.
pub mod int_type;
/// Extensions for parser database walkers with context from the connector.
pub mod walker_ext_traits;

Expand All @@ -19,6 +21,7 @@ pub use self::{
capabilities::{ConnectorCapabilities, ConnectorCapability},
empty_connector::EmptyDatamodelConnector,
filters::*,
int_type::IntType,
native_type_constructor::NativeTypeConstructor,
native_type_instance::NativeTypeInstance,
referential_integrity::ReferentialIntegrity,
Expand Down Expand Up @@ -93,6 +96,10 @@ pub trait Connector: Send + Sync {
self.referential_actions(integrity).contains(action)
}

/// Given a native integer type, returns its storage and unsignedness.
/// Returns `None` if the native type is not an integer.
fn int_type(&self, native_type: serde_json::Value) -> Option<IntType>;

/// This is used by the query engine schema builder.
///
/// For a given scalar type + native type combination, this method should return the name to be
Expand Down
4 changes: 4 additions & 0 deletions psl/psl-core/src/datamodel_connector/empty_connector.rs
Expand Up @@ -64,6 +64,10 @@ impl Connector for EmptyDatamodelConnector {
fn validate_url(&self, _url: &str) -> Result<(), String> {
Ok(())
}

fn int_type(&self, _native_type: serde_json::Value) -> Option<IntType> {
None
}
}

#[cfg(test)]
Expand Down
28 changes: 28 additions & 0 deletions psl/psl-core/src/datamodel_connector/int_type.rs
@@ -0,0 +1,28 @@
#[derive(Debug, Clone, PartialEq)]
pub enum IntType {
Signed8,
Signed16,
Signed24,
Signed32,
Unsigned8,
Unsigned16,
Unsigned24,
Unsigned32,
Custom(i64, i64),
}

impl std::fmt::Display for IntType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IntType::Signed8 => f.write_str("8-bit signed integer"),
IntType::Signed16 => f.write_str("16-bit signed integer"),
IntType::Signed24 => f.write_str("24-bit signed integer"),
IntType::Signed32 => f.write_str("32-bit signed integer"),
IntType::Unsigned8 => f.write_str("8-bit unsigned integer"),
IntType::Unsigned16 => f.write_str("16-bit unsigned integer"),
IntType::Unsigned24 => f.write_str("24-bit unsigned integer"),
IntType::Unsigned32 => f.write_str("32-bit unsigned integer"),
IntType::Custom(min, max) => write!(f, "custom integer (min: {}, max: {})", min, max),
}
}
}

0 comments on commit 5a6e984

Please sign in to comment.