@@ -117,7 +117,8 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
117117 if ! ok || j > c .off {
118118 // This group has more complete stack traces:
119119 m [k ] = group {
120- gid : uint32 (i ),
120+ // gid 0 is reserved as a sentinel value.
121+ gid : uint32 (i + 1 ),
121122 off : j ,
122123 }
123124 }
@@ -137,14 +138,14 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
137138 //
138139 // Dependencies:
139140 // - group i depends on d[i].
140- // - d[i] depends on d[d[i].gid].
141+ // - d[i] depends on d[d[i].gid-1 ].
141142 d := make ([]group , len (groups ))
142143 for i := 0 ; i < len (groups ); i ++ {
143144 g := groups [i ]
144145 t := topToken (samples [g ].LocationId )
145146 k := unsafeString (t )
146147 c , ok := m [k ]
147- if ! ok || c .off == 0 || groups [ c . gid ] == g {
148+ if ! ok || c .gid - 1 == uint32 ( i ) {
148149 // The current group has the most complete stack trace.
149150 continue
150151 }
@@ -159,21 +160,27 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
159160 g := groups [i ]
160161 c := d [i ]
161162 var off uint32
162- for c .off > 0 {
163+ var j int
164+ for c .gid > 0 && c .off > 0 {
163165 off += c .off
164- n := d [c .gid ]
165- if n .off == 0 {
166+ n := d [c .gid - 1 ]
167+ if n .gid == 0 || c . off == 0 {
166168 // Stop early to preserve c.
167169 break
168170 }
169171 c = n
172+ j ++
173+ if j == tokenLen {
174+ // Profiles with deeply recursive stack traces are ignored.
175+ return
176+ }
170177 }
171178 if off == 0 {
172179 // The current group has the most complete stack trace.
173180 continue
174181 }
175182 // The reference stack trace.
176- appx := samples [groups [c.gid ]].LocationId
183+ appx := samples [groups [c .gid - 1 ]].LocationId
177184 // It's possible that the reference stack trace does not
178185 // include the part we're looking for. In this case, we
179186 // simply ignore the group. Although it's possible to infer
0 commit comments