From 83b300435a309bef1ec76bd4f6580928ab1ecf3b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 24 Jun 2020 22:12:33 +0200 Subject: [PATCH] vweb: escape html; table: rename parent_typ to parent_type --- cmd/tools/vfmt.v | 2 +- vlib/v/checker/check_types.v | 54 +++++++++++++++++++++++------------- vlib/v/checker/checker.v | 4 +-- vlib/v/gen/cgen.v | 25 +++++++++++++---- vlib/v/gen/comptime.v | 5 ++-- vlib/v/parser/parser.v | 2 +- vlib/v/table/atypes.v | 2 +- vlib/v/table/table.v | 2 +- vlib/vweb/tmpl/tmpl.v | 4 ++- vlib/vweb/vweb.v | 6 ++++ 10 files changed, 71 insertions(+), 35 deletions(-) diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index af6b95c289..453b892e43 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -44,7 +44,7 @@ fn main() { foptions := FormatOptions{ is_c: '-c' in args is_l: '-l' in args - is_w: '-w' in args + is_w: '-ww' in args is_diff: '-diff' in args is_verbose: '-verbose' in args || '--verbose' in args is_all: '-all' in args || '--all' in args diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 54670087cf..8eb35fd3a5 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -34,20 +34,23 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool { return true } // TODO i64 as int etc - if (exp_idx in table.pointer_type_idxs || exp_idx in table.number_type_idxs) && (got_idx in - table.pointer_type_idxs || got_idx in table.number_type_idxs) { + if (exp_idx in table.pointer_type_idxs || + exp_idx in table.number_type_idxs) && + (got_idx in table.pointer_type_idxs || got_idx in table.number_type_idxs) { return true } // if exp_idx in pointer_type_idxs && got_idx in pointer_type_idxs { // return true // } // see hack in checker IndexExpr line #691 - if (got_idx == table.byte_type_idx && exp_idx == table.byteptr_type_idx) || (exp_idx == - table.byte_type_idx && got_idx == table.byteptr_type_idx) { + if (got_idx == table.byte_type_idx && + exp_idx == table.byteptr_type_idx) || + (exp_idx == table.byte_type_idx && got_idx == table.byteptr_type_idx) { return true } - if (got_idx == table.char_type_idx && exp_idx == table.charptr_type_idx) || (exp_idx == - table.char_type_idx && got_idx == table.charptr_type_idx) { + if (got_idx == table.char_type_idx && + exp_idx == table.charptr_type_idx) || + (exp_idx == table.char_type_idx && got_idx == table.charptr_type_idx) { return true } if expected == table.t_type && got == table.t_type { @@ -63,8 +66,8 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool { return true } // allow enum value to be used as int - if (got_type_sym.is_int() && exp_type_sym.kind == .enum_) || (exp_type_sym.is_int() && - got_type_sym.kind == .enum_) { + if (got_type_sym.is_int() && exp_type_sym.kind == .enum_) || + (exp_type_sym.is_int() && got_type_sym.kind == .enum_) { return true } // TODO @@ -83,13 +86,15 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool { } // TODO // accept [] when an expected type is an array - if got_type_sym.kind == .array && got_type_sym.name == 'array_void' && exp_type_sym.kind == - .array { + if got_type_sym.kind == .array && + got_type_sym.name == 'array_void' && + exp_type_sym.kind == .array { return true } // type alias - if (got_type_sym.kind == .alias && got_type_sym.parent_idx == exp_idx) || (exp_type_sym.kind == - .alias && exp_type_sym.parent_idx == got_idx) { + if (got_type_sym.kind == .alias && + got_type_sym.parent_idx == exp_idx) || + (exp_type_sym.kind == .alias && exp_type_sym.parent_idx == got_idx) { return true } // sum type @@ -271,8 +276,16 @@ pub fn (c &Checker) get_default_fmt(ftyp, typ table.Type) byte { return `p` } else { sym := c.table.get_type_symbol(ftyp) - if ftyp in [table.string_type, table.bool_type] || sym.kind in [.enum_, .array, .array_fixed, - .struct_, .map, .multi_return] || ftyp.has_flag(.optional) || sym.has_method('str') { + if sym.kind == .alias { + // string aliases should be printable + info := sym.info as table.Alias + if info.parent_type == table.string_type { + return `s` + } + } + if ftyp in [table.string_type, table.bool_type] || + sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return] || ftyp.has_flag(.optional) || + sym.has_method('str') { return `s` } else { return `_` @@ -308,12 +321,13 @@ pub fn (c &Checker) string_inter_lit(mut node ast.StringInterLiteral) table.Type if node.pluss[i] && !typ.is_number() { c.error('plus prefix only allowd for numbers', node.fmt_poss[i]) } - if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) || (typ.is_signed() && - fmt !in [`d`, `x`, `X`, `o`, `c`]) || (typ.is_any_int() && fmt !in [`d`, `c`, `x`, `X`, `o`, - `u`, `x`, `X`, `o`]) || (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || (typ.is_pointer() && - fmt !in [`p`, `x`, `X`]) || (typ.is_string() && fmt != `s`) || (typ.idx() in [table.i64_type_idx, - table.f64_type_idx - ] && fmt == `c`) { + if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) || + (typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) || + (typ.is_any_int() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) || + (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || + (typ.is_pointer() && fmt !in [`p`, `x`, `X`]) || + (typ.is_string() && fmt != `s`) || + (typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) { c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`', node.fmt_poss[i]) } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 688b4f9f79..cd0bb9ef38 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -345,7 +345,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { } if type_sym.kind == .alias { info := type_sym.info as table.Alias - if info.parent_typ.is_number() { + if info.parent_type.is_number() { c.error('cannot instantiate number type alias `$type_sym.name`', struct_init.pos) return table.void_type } @@ -363,7 +363,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { mut info := table.Struct{} if type_sym.kind == .alias { info_t := type_sym.info as table.Alias - sym := c.table.get_type_symbol(info_t.parent_typ) + sym := c.table.get_type_symbol(info_t.parent_type) if sym.kind != .struct_ { c.error('alias type name: $sym.name is not struct type', struct_init.pos) } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index cafdf7fee8..231e3788b6 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -13,8 +13,8 @@ import v.depgraph // NB: keywords after 'new' are reserved in C++ const ( - c_reserved = ['delete', 'exit', 'link', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', 'auto', - 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', + c_reserved = ['delete', 'exit', 'link', 'unix', 'error', 'calloc', 'malloc', 'free', 'panic', + 'auto', 'char', 'default', 'do', 'double', 'extern', 'float', 'inline', 'int', 'long', 'register', 'restrict', 'short', 'signed', 'sizeof', 'static', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', 'new', 'namespace', 'class', 'typename'] // same order as in token.Kind @@ -89,6 +89,7 @@ mut: sql_i int sql_stmt_name string sql_side SqlExprSide // left or right, to distinguish idents in `name == name` + inside_vweb_tmpl bool } const ( @@ -1695,13 +1696,13 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { // g.infix_op = node.op left_type := if node.left_type == table.t_type { g.cur_generic_type } else { node.left_type } left_sym := g.table.get_type_symbol(left_type) - unaliased_left := if left_sym.kind == .alias { (left_sym.info as table.Alias).parent_typ } else { left_type } + unaliased_left := if left_sym.kind == .alias { (left_sym.info as table.Alias).parent_type } else { left_type } if node.op in [.key_is, .not_is] { g.is_expr(node) return } right_sym := g.table.get_type_symbol(node.right_type) - unaliased_right := if right_sym.kind == .alias { (right_sym.info as table.Alias).parent_typ } else { node.right_type } + unaliased_right := if right_sym.kind == .alias { (right_sym.info as table.Alias).parent_type } else { node.right_type } if left_type == table.ustring_type_idx && node.op != .key_in && node.op != .not_in { fn_name := match node.op { .plus { @@ -3004,7 +3005,13 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { // Build args for i, expr in node.exprs { if node.expr_types[i] == table.string_type { - g.expr(expr) + if g.inside_vweb_tmpl { + g.write('vweb__filter(') + g.expr(expr) + g.write(')') + } else { + g.expr(expr) + } } else if node.expr_types[i] == table.bool_type { g.expr(expr) g.write(' ? _SLIT("true") : _SLIT("false")') @@ -3049,7 +3056,13 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool { g.write('${str_fn_name}(') g.expr(expr) g.write(')') - } else if sym.kind == .enum_ { + } + else if sym.kind == .alias && (sym.info as table.Alias).parent_type == table.string_type { + // handle string aliases + g.expr(expr) + return true + } + else if sym.kind == .enum_ { is_var := match expr { ast.SelectorExpr { true } ast.Ident { true } diff --git a/vlib/v/gen/comptime.v b/vlib/v/gen/comptime.v index e3d91e3b19..3ee15ae9bf 100644 --- a/vlib/v/gen/comptime.v +++ b/vlib/v/gen/comptime.v @@ -13,7 +13,9 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) { fn_decl := stmt as ast.FnDecl // insert stmts from vweb_tmpl fn if fn_decl.name.starts_with('vweb_tmpl') { + g.inside_vweb_tmpl = true g.stmts(fn_decl.stmts) + g.inside_vweb_tmpl = false break } } @@ -23,8 +25,7 @@ fn (g &Gen) comptime_call(node ast.ComptimeCall) { } g.writeln('// $' + 'method call. sym="$node.sym.name"') mut j := 0 - result_type := g.table.find_type_idx('vweb.Result') - println('!!!!! $result_type') + result_type := g.table.find_type_idx('vweb.Result') // TODO not just vweb for method in node.sym.methods { // if method.return_type != table.void_type { if method.return_type != result_type { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 52e3a60556..6272817da8 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1577,7 +1577,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl { parent_idx: pid mod: p.mod info: table.Alias{ - parent_typ: parent_type + parent_type: parent_type language: language } is_public: is_pub diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index 1882376a46..318f7321da 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -634,7 +634,7 @@ pub: pub struct Alias { pub: - parent_typ Type + parent_type Type language Language } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 163de2a794..14441b4ce2 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -202,7 +202,7 @@ pub fn (t &Table) get_type_name(typ Type) string { pub fn (t &Table) unalias_num_type(typ Type) Type { sym := t.get_type_symbol(typ) if sym.kind == .alias { - pt := (sym.info as Alias).parent_typ + pt := (sym.info as Alias).parent_type if pt <= f64_type && pt >= void_type { return pt } diff --git a/vlib/vweb/tmpl/tmpl.v b/vlib/vweb/tmpl/tmpl.v index 5c1ca50b6e..6ade4a7753 100644 --- a/vlib/vweb/tmpl/tmpl.v +++ b/vlib/vweb/tmpl/tmpl.v @@ -152,7 +152,8 @@ _ = footer } } else { // HTML, may include `@var` - s.writeln(line.replace('@', '\x24').replace("'", '"')) + // escaped by cgen, unless it's a `vweb.RawHtml` string + s.writeln(line.replace('@', '$').replace("'", '"')) } } s.writeln(str_end) @@ -161,3 +162,4 @@ _ = footer s.writeln('// === end of vweb html template ===') return s.str() } + diff --git a/vlib/vweb/vweb.v b/vlib/vweb/vweb.v index 32c594a3af..416c274d81 100644 --- a/vlib/vweb/vweb.v +++ b/vlib/vweb/vweb.v @@ -411,3 +411,9 @@ fn strip(s string) string { pub fn not_found() Result { return Result{} } + +fn filter(s string) string { + return s.replace('<', '<') +} + +pub type RawHtml = string