From a3e1d2fde21364528b8f4980a23c90d18561b7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Houl=C3=A9?= Date: Wed, 30 Nov 2022 13:24:14 +0100 Subject: [PATCH] psl: fix newline boundary search in relation reformatting 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 https://github.com/prisma/prisma/issues/14895 --- psl/psl-core/src/reformat.rs | 16 ++++++------- psl/psl/tests/reformat_tests.rs | 2 ++ ...ld_with_multi_byte_trailing_comment.prisma | 23 +++++++++++++++++++ ...i_byte_trailing_comment.reformatted.prisma | 23 +++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma create mode 100644 psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma diff --git a/psl/psl-core/src/reformat.rs b/psl/psl-core/src/reformat.rs index d2ce95518505..129576dd6325 100644 --- a/psl/psl-core/src/reformat.rs +++ b/psl/psl-core/src/reformat.rs @@ -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, }) } @@ -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) } diff --git a/psl/psl/tests/reformat_tests.rs b/psl/psl/tests/reformat_tests.rs index 1d070107a7d5..ea6207894047 100644 --- a/psl/psl/tests/reformat_tests.rs +++ b/psl/psl/tests/reformat_tests.rs @@ -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."); } } diff --git a/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma new file mode 100644 index 000000000000..faa11066ff2a --- /dev/null +++ b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.prisma @@ -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[] +} diff --git a/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma new file mode 100644 index 000000000000..410deb2686d8 --- /dev/null +++ b/psl/psl/tests/reformatter/regression_add_relation_attribute_on_field_with_multi_byte_trailing_comment.reformatted.prisma @@ -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[] +}