@@ -117,7 +117,8 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
117
117
if ! ok || j > c .off {
118
118
// This group has more complete stack traces:
119
119
m [k ] = group {
120
- gid : uint32 (i ),
120
+ // gid 0 is reserved as a sentinel value.
121
+ gid : uint32 (i + 1 ),
121
122
off : j ,
122
123
}
123
124
}
@@ -137,14 +138,14 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
137
138
//
138
139
// Dependencies:
139
140
// - 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 ].
141
142
d := make ([]group , len (groups ))
142
143
for i := 0 ; i < len (groups ); i ++ {
143
144
g := groups [i ]
144
145
t := topToken (samples [g ].LocationId )
145
146
k := unsafeString (t )
146
147
c , ok := m [k ]
147
- if ! ok || c .off == 0 || groups [ c . gid ] == g {
148
+ if ! ok || c .gid - 1 == uint32 ( i ) {
148
149
// The current group has the most complete stack trace.
149
150
continue
150
151
}
@@ -159,21 +160,27 @@ func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
159
160
g := groups [i ]
160
161
c := d [i ]
161
162
var off uint32
162
- for c .off > 0 {
163
+ var j int
164
+ for c .gid > 0 && c .off > 0 {
163
165
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 {
166
168
// Stop early to preserve c.
167
169
break
168
170
}
169
171
c = n
172
+ j ++
173
+ if j == tokenLen {
174
+ // Profiles with deeply recursive stack traces are ignored.
175
+ return
176
+ }
170
177
}
171
178
if off == 0 {
172
179
// The current group has the most complete stack trace.
173
180
continue
174
181
}
175
182
// The reference stack trace.
176
- appx := samples [groups [c.gid ]].LocationId
183
+ appx := samples [groups [c .gid - 1 ]].LocationId
177
184
// It's possible that the reference stack trace does not
178
185
// include the part we're looking for. In this case, we
179
186
// simply ignore the group. Although it's possible to infer
0 commit comments