nil in string concats does not produce crashes anymore

This commit is contained in:
Andreas Rumpf
2018-04-27 21:32:58 +02:00
parent c8a412998a
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}:
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)

View File

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

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