@@ -221,29 +221,57 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
221221 for (LocalInfo &local : frame.locals ) {
222222 if (!local.has_frame_offset || !local.has_size || !local.has_tag_offset )
223223 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 ;
224228 tag_t obj_tag = base_tag ^ local.tag_offset ;
225229 if (obj_tag != addr_tag)
226230 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+
236237 if (!found_local) {
237238 Printf (" \n Potentially referenced stack objects:\n " );
238239 found_local = true ;
239240 }
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 ());
240267 StackTracePrinter::GetOrInit ()->RenderSourceLocation (
241268 &location, local.decl_file , local.decl_line , /* column= */ 0 ,
242269 common_flags ()->symbolize_vs_style ,
243270 common_flags ()->strip_path_prefix );
244271 Printf (" %s in %s %s\n " , local.name , local.function_name ,
245272 location.data ());
246273 location.clear ();
274+ Printf (" %s\n " , d.Default ());
247275 }
248276 frame.Clear ();
249277 }
@@ -751,8 +779,6 @@ void BaseReport::PrintAddressDescription() const {
751779 // Check stack first. If the address is on the stack of a live thread, we
752780 // know it cannot be a heap / global overflow.
753781 for (const auto &sa : allocations.stack ) {
754- // TODO(fmayer): figure out how to distinguish use-after-return and
755- // stack-buffer-overflow.
756782 Printf (" %s" , d.Error ());
757783 Printf (" \n Cause: stack tag-mismatch\n " );
758784 Printf (" %s" , d.Location ());
0 commit comments