nil in string concats does not produce crashes anymore

This commit is contained in:
Andreas Rumpf 2018-04-27 21:32:58 +02:00
commit 7c538b26ad
3 changed files with 42 additions and 12 deletions

View file

@ -1034,7 +1034,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
inc(L, len(e.sons[i + 1].strVal)) inc(L, len(e.sons[i + 1].strVal))
else: 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))) 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)) linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
add(p.s(cpsStmts), appends) add(p.s(cpsStmts), appends)

View file

@ -161,14 +161,16 @@ proc hashString(s: string): int {.compilerproc.} =
proc addChar(s: NimString, c: char): NimString = proc addChar(s: NimString, c: char): NimString =
# is compilerproc! # is compilerproc!
result = s if s == nil:
if result.len >= result.space: result = rawNewStringNoInit(1)
let r = resize(result.space) result.len = 0
result = cast[NimString](growObj(result, else:
sizeof(TGenericSeq) + r + 1)) result = s
result.reserved = r if result.len >= result.space:
elif wasMoved(s): let r = resize(result.space)
result = newOwnedString(s, s.len) result = cast[NimString](growObj(result,
sizeof(TGenericSeq) + r + 1))
result.reserved = r
result.data[result.len] = c result.data[result.len] = c
result.data[result.len+1] = '\0' result.data[result.len+1] = '\0'
inc(result.len) inc(result.len)
@ -205,7 +207,9 @@ proc addChar(s: NimString, c: char): NimString =
# s = rawNewString(0); # s = rawNewString(0);
proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} = 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 result = dest
else: # slow path: else: # slow path:
var sp = max(resize(dest.space), dest.len + addlen) 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 # DO NOT UPDATE LEN YET: dest.len = newLen
proc appendString(dest, src: NimString) {.compilerproc, inline.} = proc appendString(dest, src: NimString) {.compilerproc, inline.} =
copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1) if src != nil:
inc(dest.len, src.len) 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.} = proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
dest.data[dest.len] = c dest.data[dest.len] = c

View file

@ -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