From 7170a093823b34dfdf3616016b2d4db8f43d9547 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 5 May 2022 07:36:56 +0300 Subject: [PATCH] vfmt: fix stackoverflow on long nested infix expressions --- vlib/v/fmt/fmt.v | 12 ++++++ .../tests/too_long_infix_expressions_keep.vv | 40 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 vlib/v/fmt/tests/too_long_infix_expressions_keep.vv diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 8b28b89f0b..d79364f189 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -48,6 +48,7 @@ pub mut: inside_const bool is_mbranch_expr bool // match a { x...y { } } fn_scope &ast.Scope = voidptr(0) + wsinfix_depth int } pub fn fmt(file ast.File, table &ast.Table, pref &pref.Preferences, is_debug bool) string { @@ -2075,7 +2076,13 @@ fn split_up_infix(infix_str string, ignore_paren bool, is_cond_infix bool) ([]st return conditions, penalties } +const wsinfix_depth_max = 10 + fn (mut f Fmt) write_splitted_infix(conditions []string, penalties []int, ignore_paren bool, is_cond bool) { + f.wsinfix_depth++ + defer { + f.wsinfix_depth-- + } for i, cnd in conditions { c := cnd.trim_space() if f.line_len + c.len < fmt.max_len[penalties[i]] { @@ -2086,6 +2093,11 @@ fn (mut f Fmt) write_splitted_infix(conditions []string, penalties []int, ignore } else { is_paren_expr := (c[0] == `(` || (c.len > 5 && c[3] == `(`)) && c.ends_with(')') final_len := ((f.indent + 1) * 4) + c.len + if f.wsinfix_depth > fmt.wsinfix_depth_max { + // limit indefinite recursion, by just giving up splitting: + f.write(c) + continue + } if final_len > fmt.max_len.last() && is_paren_expr { conds, pens := split_up_infix(c, true, is_cond) f.write_splitted_infix(conds, pens, true, is_cond) diff --git a/vlib/v/fmt/tests/too_long_infix_expressions_keep.vv b/vlib/v/fmt/tests/too_long_infix_expressions_keep.vv new file mode 100644 index 0000000000..79c0084075 --- /dev/null +++ b/vlib/v/fmt/tests/too_long_infix_expressions_keep.vv @@ -0,0 +1,40 @@ +module main + +struct Abc { +pub mut: + x int + y int + angle int +} + +fn s_adjustsoundparams(listener &Abc, source &Abc, vol &int, sep &int) int { + approx_dist := 0 + adx := 0 + ady := 0 + angle := 0 + adx = C.abs(listener.x - source.x) + ady = C.abs(listener.y - source.y) + approx_dist = adx + ady - ((if adx < ady { adx } else { ady }) >> 1) + if gamemap != 8 && approx_dist > (1200 * (1 << 16)) { + return 0 + } + angle = r_pointtoangle2(listener.x, listener.y, source.x, source.y) + if angle > listener.angle { + angle = angle - listener.angle + } else { + angle = angle + (4294967295 - listener.angle) + } + angle >>= 19 + *sep = 128 - (fixedmul((96 * (1 << 16)), finesine[angle]) >> 16) + if approx_dist < (200 * (1 << 16)) { + *vol = snd_SfxVolume + } else if gamemap == 8 { + if approx_dist > (1200 * (1 << 16)) { + approx_dist = (1200 * (1 << 16)) + } + *vol = 15 +((snd_SfxVolume - 15) * (((1200 * (1 << 16)) - approx_dist) >> 16)) / (((1200 * (1 << 16)) - (200 * (1 << 16))) >> 16) + } else { + *vol = (snd_SfxVolume * (((1200 * (1 << 16)) - approx_dist) >> 16)) / (((1200 * (1 << 16)) - (200 * (1 << 16))) >> 16) + } + return *vol > 0 +}