Skip to content

Commit

Permalink
psl: fix newline boundary search in relation reformatting
Browse files Browse the repository at this point in the history
When adding an @relation attribute to a forward relation field in the
relation reformatting code that deals with adding missing relation
fields and attributes, we searched for the last character before a
newline to check whether it is a carriage return, but we failed to
check whether the byte offset was a char boundary first. This caused
crashes.

closes prisma/prisma#14895
  • Loading branch information
tomhoule committed Dec 1, 2022
1 parent 31ead21 commit a3e1d2f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
16 changes: 7 additions & 9 deletions psl/psl-core/src/reformat.rs
Expand Up @@ -137,7 +137,7 @@ fn push_missing_relation_attribute(inline_relation: walkers::InlineRelationWalke
content.push(')');

ctx.missing_bits.push(MissingBit {
position: before_newline(forward.ast_field().span().end, ctx.original_schema),
position: after_type(forward.ast_field().field_type.span().end, ctx.original_schema),
content,
})
}
Expand Down Expand Up @@ -328,12 +328,10 @@ fn references_argument(inline: walkers::InlineRelationWalker<'_>) -> String {
format!("references: [{}]", field_names.join(", "))
}

/// Assuming the last characters before span_end are newlines. We can fix this more thoroughly by
/// not including the newline in field spans.
fn before_newline(span_end: usize, original_schema: &str) -> usize {
assert!(&original_schema[span_end - 1..span_end] == "\n");
match &original_schema[span_end - 2..span_end - 1] {
"\r" => span_end - 2,
_ => span_end - 1,
}
fn after_type(type_span_end: usize, original_schema: &str) -> usize {
original_schema[type_span_end..]
.chars()
.position(|chr| !['[', ']', '?', '!'].contains(&chr))
.map(|pos| type_span_end + pos)
.unwrap_or(type_span_end)
}
2 changes: 2 additions & 0 deletions psl/psl/tests/reformat_tests.rs
Expand Up @@ -28,6 +28,8 @@ fn run_reformat_test(test_file_path: &str) {
}

if reformat(&reformatted_text) != reformatted_text {
println!("=== reformatted ===\n{reformatted_text}");
println!("=== reformatted again ===\n{}", reformat(&reformatted_text));
panic!("Reformatting this schema is not idempotent.");
}
}
Expand Down
@@ -0,0 +1,23 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
output = "./generated/client"
}

datasource db {
provider = "sqlserver"
url = "***"
}

model somemodel {
frownyFaceId String
frownyFace frownyface // 囧
id Int @id
}

model frownyface {
somes somemodel[]
}
@@ -0,0 +1,23 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
provider = "prisma-client-js"
output = "./generated/client"
}

datasource db {
provider = "sqlserver"
url = "***"
}

model somemodel {
frownyFaceId String
frownyFace frownyface @relation(fields: [], references: []) // 囧
id Int @id
}

model frownyface {
somes somemodel[]
}

0 comments on commit a3e1d2f

Please sign in to comment.