From 34d115d883c167731269a93e8439ecf9552be3e4 Mon Sep 17 00:00:00 2001 From: shove Date: Tue, 11 Oct 2022 12:48:26 +0800 Subject: [PATCH] cgen: fix wrong when string attributes with quotes (fix #15194) (#16020) --- vlib/v/gen/c/comptime.v | 3 +++ vlib/v/gen/c/testdata/attr_string_quotes_escape.out | 7 +++++++ vlib/v/gen/c/testdata/attr_string_quotes_escape.vv | 11 +++++++++++ vlib/v/gen/c/utils.v | 12 ++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 vlib/v/gen/c/testdata/attr_string_quotes_escape.out create mode 100644 vlib/v/gen/c/testdata/attr_string_quotes_escape.vv diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index 40d85f77ee..500aed8d9d 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -202,6 +202,9 @@ fn cgen_attrs(attrs []ast.Attr) []string { if attr.arg.len > 0 { s += ': $attr.arg' } + if attr.kind == .string { + s = escape_quotes(s) + } res << '_SLIT("$s")' } return res diff --git a/vlib/v/gen/c/testdata/attr_string_quotes_escape.out b/vlib/v/gen/c/testdata/attr_string_quotes_escape.out new file mode 100644 index 0000000000..261e944604 --- /dev/null +++ b/vlib/v/gen/c/testdata/attr_string_quotes_escape.out @@ -0,0 +1,7 @@ +FunctionData{ + name: 'sample_method' + attrs: ['option: "1"'] + args: [] + return_type: 1 + typ: 0 +} diff --git a/vlib/v/gen/c/testdata/attr_string_quotes_escape.vv b/vlib/v/gen/c/testdata/attr_string_quotes_escape.vv new file mode 100644 index 0000000000..a4fd8636b5 --- /dev/null +++ b/vlib/v/gen/c/testdata/attr_string_quotes_escape.vv @@ -0,0 +1,11 @@ +struct Dummy {} + +['option: "1"'] +fn (d Dummy) sample_method() { +} + +fn main() { + $for method in Dummy.methods { + println(method) + } +} diff --git a/vlib/v/gen/c/utils.v b/vlib/v/gen/c/utils.v index e61bb6214c..aaef3ea208 100644 --- a/vlib/v/gen/c/utils.v +++ b/vlib/v/gen/c/utils.v @@ -83,3 +83,15 @@ fn (mut g Gen) fn_var_signature(return_type ast.Type, arg_types []ast.Type, var_ sig += ')' return sig } + +// escape quotes for string +fn escape_quotes(val string) string { + bs := '\\' + unescaped_val := val.replace('$bs$bs', '\x01').replace_each([ + "$bs'", + "'", + '$bs"', + '"', + ]) + return unescaped_val.replace_each(['\x01', '$bs$bs', "'", "$bs'", '"', '$bs"']) +}