From 7c538b26ad03b077da84766771b85d72d978b598 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 27 Apr 2018 21:32:58 +0200 Subject: [PATCH] nil in string concats does not produce crashes anymore --- compiler/ccgexprs.nim | 2 +- lib/system/sysstr.nim | 27 ++++++++++++++++----------- tests/system/tnilconcats.nim | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 tests/system/tnilconcats.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7040b75c6..a2789138b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1034,7 +1034,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 1].strVal)) else: - addf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)]) + addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)]) add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L)) add(p.s(cpsStmts), appends) diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 42aae6654..e64e12fc7 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -161,14 +161,16 @@ proc hashString(s: string): int {.compilerproc.} = proc addChar(s: NimString, c: char): NimString = # is compilerproc! - result = s - if result.len >= result.space: - let r = resize(result.space) - result = cast[NimString](growObj(result, - sizeof(TGenericSeq) + r + 1)) - result.reserved = r - elif wasMoved(s): - result = newOwnedString(s, s.len) + if s == nil: + result = rawNewStringNoInit(1) + result.len = 0 + else: + result = s + if result.len >= result.space: + let r = resize(result.space) + result = cast[NimString](growObj(result, + sizeof(TGenericSeq) + r + 1)) + result.reserved = r result.data[result.len] = c result.data[result.len+1] = '\0' inc(result.len) @@ -205,7 +207,9 @@ proc addChar(s: NimString, c: char): NimString = # s = rawNewString(0); proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} = - if dest.len + addlen <= dest.space and not wasMoved(dest): + if dest == nil: + result = rawNewStringNoInit(addlen) + elif dest.len + addlen <= dest.space and not wasMoved(dest): result = dest else: # slow path: var sp = max(resize(dest.space), dest.len + addlen) @@ -216,8 +220,9 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} = # DO NOT UPDATE LEN YET: dest.len = newLen proc appendString(dest, src: NimString) {.compilerproc, inline.} = - copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1) - inc(dest.len, src.len) + if src != nil: + copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1) + inc(dest.len, src.len) proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} = dest.data[dest.len] = c diff --git a/tests/system/tnilconcats.nim b/tests/system/tnilconcats.nim new file mode 100644 index 000000000..ce059b7b0 --- /dev/null +++ b/tests/system/tnilconcats.nim @@ -0,0 +1,25 @@ +discard """ + output: '''@[nil, nil, nil, nil, nil, nil, nil, "meh"]''' + exitcode: "0" +""" + +when true: + var ab: string + ab &= "more" + + doAssert ab == "more" + + var x: seq[string] + + setLen(x, 7) + + x.add "meh" + + var s: string + var z = "abc" + var zz: string + s &= "foo" & z & zz + + doAssert s == "fooabc" + + echo x