Browse Source

Merge pull request #3929 from laytan/fix-fmt-len-transfer-to-children

fmt: fix optional_len or use_nul_termination being used by both array and elems
Jeroen van Rijn 1 year ago
parent
commit
0a9c150748
2 changed files with 24 additions and 0 deletions
  1. 8 0
      core/fmt/fmt.odin
  2. 16 0
      tests/core/fmt/test_core_fmt.odin

+ 8 - 0
core/fmt/fmt.odin

@@ -2751,9 +2751,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 			elem := runtime.type_info_base(info.elem)
 			if elem != nil {
 				if n, ok := fi.optional_len.?; ok {
+					fi.optional_len = nil
 					fmt_array(fi, ptr, n, elem.size, elem, verb)
 					return
 				} else if fi.use_nul_termination {
+					fi.use_nul_termination = false
 					fmt_array_nul_terminated(fi, ptr, -1, elem.size, elem, verb)
 					return
 				}
@@ -2855,8 +2857,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		n := info.count
 		ptr := v.data
 		if ol, ok := fi.optional_len.?; ok {
+			fi.optional_len = nil
 			n = min(n, ol)
 		} else if fi.use_nul_termination {
+			fi.use_nul_termination = false
 			fmt_array_nul_terminated(fi, ptr, n, info.elem_size, info.elem, verb)
 			return
 		}
@@ -2867,8 +2871,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		n := slice.len
 		ptr := slice.data
 		if ol, ok := fi.optional_len.?; ok {
+			fi.optional_len = nil
 			n = min(n, ol)
 		} else if fi.use_nul_termination {
+			fi.use_nul_termination = false
 			fmt_array_nul_terminated(fi, ptr, n, info.elem_size, info.elem, verb)
 			return
 		}
@@ -2879,8 +2885,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		n := array.len
 		ptr := array.data
 		if ol, ok := fi.optional_len.?; ok {
+			fi.optional_len = nil
 			n = min(n, ol)
 		} else if fi.use_nul_termination {
+			fi.use_nul_termination = false
 			fmt_array_nul_terminated(fi, ptr, n, info.elem_size, info.elem, verb)
 			return
 		}

+ 16 - 0
tests/core/fmt/test_core_fmt.odin

@@ -372,6 +372,22 @@ test_odin_value_export :: proc(t: ^testing.T) {
 	}
 }
 
+@(test)
+leaking_struct_tag :: proc(t: ^testing.T) {
+	My_Struct :: struct {
+		names:      [^]string `fmt:"v,name_count"`,
+		name_count: int,
+	}
+
+	name := "hello?"
+	foo := My_Struct {
+		names = &name,
+		name_count = 1,
+	}
+
+	check(t, "My_Struct{names = [\"hello?\"], name_count = 1}", "%v", foo)
+}
+
 @(private)
 check :: proc(t: ^testing.T, exp: string, format: string, args: ..any, loc := #caller_location) {
 	got := fmt.tprintf(format, ..args)