@@ -221,29 +221,57 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
221
221
for (LocalInfo &local : frame.locals ) {
222
222
if (!local.has_frame_offset || !local.has_size || !local.has_tag_offset )
223
223
continue ;
224
+ if (!(local.name && internal_strlen (local.name )) &&
225
+ !(local.function_name && internal_strlen (local.name )) &&
226
+ !(local.decl_file && internal_strlen (local.decl_file )))
227
+ continue ;
224
228
tag_t obj_tag = base_tag ^ local.tag_offset ;
225
229
if (obj_tag != addr_tag)
226
230
continue ;
227
- // Calculate the offset from the object address to the faulting
228
- // address. Because we only store bits 4-19 of FP (bits 0-3 are
229
- // guaranteed to be zero), the calculation is performed mod 2^20 and may
230
- // harmlessly underflow if the address mod 2^20 is below the object
231
- // address.
232
- uptr obj_offset =
233
- (untagged_addr - fp - local.frame_offset ) & (kRecordFPModulus - 1 );
234
- if (obj_offset >= local.size )
235
- continue ;
231
+ // Guess top bits of local variable from the faulting address, because
232
+ // we only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
233
+ uptr local_beg = (fp + local.frame_offset ) |
234
+ (untagged_addr & ~(uptr (kRecordFPModulus ) - 1 ));
235
+ uptr local_end = local_beg + local.size ;
236
+
236
237
if (!found_local) {
237
238
Printf (" \n Potentially referenced stack objects:\n " );
238
239
found_local = true ;
239
240
}
241
+
242
+ uptr offset;
243
+ const char *whence;
244
+ const char *cause;
245
+ if (local_beg <= untagged_addr && untagged_addr < local_end) {
246
+ offset = untagged_addr - local_beg;
247
+ whence = " inside" ;
248
+ cause = " use-after-scope" ;
249
+ } else if (untagged_addr >= local_end) {
250
+ offset = untagged_addr - local_end;
251
+ whence = " after" ;
252
+ cause = " stack-buffer-overflow" ;
253
+ } else {
254
+ offset = local_beg - untagged_addr;
255
+ whence = " before" ;
256
+ cause = " stack-buffer-overflow" ;
257
+ }
258
+ Decorator d;
259
+ Printf (" %s" , d.Error ());
260
+ Printf (" Cause: %s\n " , cause);
261
+ Printf (" %s" , d.Default ());
262
+ Printf (" %s" , d.Location ());
263
+ Printf (" %p is located %zd bytes %s a %zd-byte region [%p,%p)\n " ,
264
+ untagged_addr, offset, whence, local_end - local_beg, local_beg,
265
+ local_end);
266
+ Printf (" %s" , d.Allocation ());
240
267
StackTracePrinter::GetOrInit ()->RenderSourceLocation (
241
268
&location, local.decl_file , local.decl_line , /* column= */ 0 ,
242
269
common_flags ()->symbolize_vs_style ,
243
270
common_flags ()->strip_path_prefix );
244
271
Printf (" %s in %s %s\n " , local.name , local.function_name ,
245
272
location.data ());
246
273
location.clear ();
274
+ Printf (" %s\n " , d.Default ());
247
275
}
248
276
frame.Clear ();
249
277
}
@@ -751,8 +779,6 @@ void BaseReport::PrintAddressDescription() const {
751
779
// Check stack first. If the address is on the stack of a live thread, we
752
780
// know it cannot be a heap / global overflow.
753
781
for (const auto &sa : allocations.stack ) {
754
- // TODO(fmayer): figure out how to distinguish use-after-return and
755
- // stack-buffer-overflow.
756
782
Printf (" %s" , d.Error ());
757
783
Printf (" \n Cause: stack tag-mismatch\n " );
758
784
Printf (" %s" , d.Location ());
0 commit comments