@@ -339,7 +339,7 @@ fn (a string) option_clone_static() ?string {
339339
340340// clone returns a copy of the V string `a`.
341341pub fn (a string) clone () string {
342- if a.len < = 0 {
342+ if a.len < = 0 || u64 (a.str) < = 0xFFFF {
343343 return ''
344344 }
345345 mut b := string {
@@ -783,8 +783,9 @@ pub fn (s string) parse_int(_base int, _bit_size int) !i64 {
783783@[direct_array_access]
784784fn (s string ) == (a string ) bool {
785785 if s.str == 0 {
786- // should never happen
787- panic ('string.eq(): nil string' )
786+ // Nil string: equal only to another nil/empty string.
787+ // This can happen with zero-initialized struct fields in the native backend.
788+ return a.str == 0 || a.len == 0
788789 }
789790 if s.len != a.len {
790791 return false
@@ -832,16 +833,20 @@ fn (s string) < (a string) bool {
832833
833834@[direct_array_access]
834835fn (s string ) + (a string ) string {
835- new_len := a.len + s.len
836+ slen := if s.len > 0 && u64 (s.str) > 0xFFFF { s.len } else { 0 }
837+ alen := if a.len > 0 && u64 (a.str) > 0xFFFF { a.len } else { 0 }
838+ new_len := alen + slen
836839 mut res := string {
837840 str: unsafe { malloc_noscan (new_len + 1 ) }
838841 len: new_len
839842 }
840843 unsafe {
841- vmemcpy (res.str, s.str, s.len)
842- vmemcpy (res.str + s.len, a.str, a.len)
843- }
844- unsafe {
844+ if slen > 0 {
845+ vmemcpy (res.str, s.str, slen)
846+ }
847+ if alen > 0 {
848+ vmemcpy (res.str + slen, a.str, alen)
849+ }
845850 res.str[new_len] = 0 // V strings are not null terminated, but just in case
846851 }
847852 return res
@@ -850,17 +855,24 @@ fn (s string) + (a string) string {
850855// for `s + s2 + s3`, an optimization (faster than string_plus(string_plus(s1, s2), s3))
851856@[direct_array_access]
852857fn (s string) plus_two (a string , b string ) string {
853- new_len := a.len + b.len + s.len
858+ slen := if s.len > 0 && u64 (s.str) > 0xFFFF { s.len } else { 0 }
859+ alen := if a.len > 0 && u64 (a.str) > 0xFFFF { a.len } else { 0 }
860+ blen := if b.len > 0 && u64 (b.str) > 0xFFFF { b.len } else { 0 }
861+ new_len := alen + blen + slen
854862 mut res := string {
855863 str: unsafe { malloc_noscan (new_len + 1 ) }
856864 len: new_len
857865 }
858866 unsafe {
859- vmemcpy (res.str, s.str, s.len)
860- vmemcpy (res.str + s.len, a.str, a.len)
861- vmemcpy (res.str + s.len + a.len, b.str, b.len)
862- }
863- unsafe {
867+ if slen > 0 {
868+ vmemcpy (res.str, s.str, slen)
869+ }
870+ if alen > 0 {
871+ vmemcpy (res.str + slen, a.str, alen)
872+ }
873+ if blen > 0 {
874+ vmemcpy (res.str + slen + alen, b.str, blen)
875+ }
864876 res.str[new_len] = 0 // V strings are not null terminated, but just in case
865877 }
866878 return res
@@ -1269,7 +1281,7 @@ pub fn (s string) substr_ni(_start int, _end int) string {
12691281// It will return `-1` if the input string can't be found.
12701282@[direct_array_access]
12711283pub fn (s string) index_ (p string ) int {
1272- if p.len > s.len || p.len == 0 {
1284+ if p.len > s.len || p.len == 0 || u64 (s.str) < = 0xFFFF || u64 (p.str) < = 0xFFFF {
12731285 return - 1
12741286 }
12751287 if p.len > 2 {
@@ -1572,7 +1584,7 @@ pub fn (s string) contains_any_substr(substrs []string) bool {
15721584// starts_with returns `true` if the string starts with `p`.
15731585@[direct_array_access]
15741586pub fn (s string) starts_with (p string ) bool {
1575- if p.len > s.len {
1587+ if p.len > s.len || u64 (s.str) < = 0xFFFF || u64 (p.str) < = 0xFFFF {
15761588 return false
15771589 } else if unsafe { vmemcmp (s.str, p.str, p.len) == 0 } {
15781590 return true
@@ -1583,7 +1595,7 @@ pub fn (s string) starts_with(p string) bool {
15831595// ends_with returns `true` if the string ends with `p`.
15841596@[direct_array_access]
15851597pub fn (s string) ends_with (p string ) bool {
1586- if p.len > s.len {
1598+ if p.len > s.len || u64 (s.str) < = 0xFFFF || u64 (p.str) < = 0xFFFF {
15871599 return false
15881600 } else if unsafe { vmemcmp (s.str + s.len - p.len, p.str, p.len) == 0 } {
15891601 return true
0 commit comments