summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/system/strs_v2.nim13
-rw-r--r--tests/destructor/tnewruntime_strutils.nim32
2 files changed, 38 insertions, 7 deletions
diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim
index f51791da2..fe117997b 100644
--- a/lib/system/strs_v2.nim
+++ b/lib/system/strs_v2.nim
@@ -40,21 +40,22 @@ proc resize(old: int): int {.inline.} =
   else: result = old * 3 div 2 # for large arrays * 3/2 is better
 
 proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
+  let newLen = s.len + addlen
   if isLiteral(s):
     let oldP = s.p
     # can't mutate a literal, so we need a fresh copy here:
     when compileOption("threads"):
-      s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len + addlen)))
+      s.p = cast[ptr NimStrPayload](allocShared0(contentSize(newLen)))
     else:
-      s.p = cast[ptr NimStrPayload](alloc0(contentSize(s.len + addlen)))
-    s.p.cap = s.len + addlen
+      s.p = cast[ptr NimStrPayload](alloc0(contentSize(newLen)))
+    s.p.cap = newLen
     if s.len > 0:
       # we are about to append, so there is no need to copy the \0 terminator:
-      copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
+      copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], min(s.len, newLen))
   else:
     let oldCap = s.p.cap and not strlitFlag
-    if s.len + addlen > oldCap:
-      let newCap = max(s.len + addlen, resize(oldCap))
+    if newLen > oldCap:
+      let newCap = max(newLen, resize(oldCap))
       when compileOption("threads"):
         s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(oldCap), contentSize(newCap)))
       else:
diff --git a/tests/destructor/tnewruntime_strutils.nim b/tests/destructor/tnewruntime_strutils.nim
index b0bceb4b5..0725718d7 100644
--- a/tests/destructor/tnewruntime_strutils.nim
+++ b/tests/destructor/tnewruntime_strutils.nim
@@ -2,7 +2,10 @@ discard """
   valgrind: true
   cmd: '''nim c -d:nimAllocStats --newruntime -d:useMalloc $file'''
   output: '''
-@[(input: @["KXSC", "BGMC"]), (input: @["PXFX"]), (input: @["WXRQ", "ZSCZD"])]'''
+@[(input: @["KXSC", "BGMC"]), (input: @["PXFX"]), (input: @["WXRQ", "ZSCZD"])]
+14
+First tasks completed.
+Second tasks completed.'''
 """
 
 import strutils, os, std / wordwrap
@@ -211,3 +214,30 @@ staticTests()
 # bug #12965
 let xaa = @[""].join()
 let xbb = @["", ""].join()
+
+# bug #16365
+
+# Task 1:
+when true:
+  # Task 1_a:
+  var test_string_a = "name_something"
+  echo test_string_a.len()
+  let new_len_a = test_string_a.len - "_something".len()
+  test_string_a.setLen new_len_a
+
+  echo "First tasks completed."
+
+# Task 2:
+when true:
+  # Task 2_a
+  var test_string: string
+  let some_string = "something"
+  for i in some_string.items:
+    test_string.add $i
+
+  # Task 2_b
+  var test_string_b = "name_something"
+  let new_len_b = test_string_b.len - "_something".len()
+  test_string_b.setLen new_len_b
+
+  echo "Second tasks completed."