From 8b7c63e38524b1bcee9f33ca58f38c13dca17fd3 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Mon, 9 May 2022 16:01:47 -0400 Subject: [PATCH] [5.7][Reflection] Gracefully handle reflection sections with bad sizes. When a reflection section has a size that only fits a partial record, we detect it, log an error, and abort. However, things like Remote Mirror need to be robust to bad data, so instead handle this by terminating iteration at the last full record. rdar://91954103 (cherry picked from commit 5d1f63597bd210b198892368bdc6e720eb9c4bd5) --- include/swift/Reflection/TypeRefBuilder.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h index 546033a6ad493..e63c3cfacce8f 100644 --- a/include/swift/Reflection/TypeRefBuilder.h +++ b/include/swift/Reflection/TypeRefBuilder.h @@ -100,6 +100,12 @@ class ReflectionSectionIteratorBase : OriginalSize(Size), Cur(Cur), Size(Size), Name(Name) { if (Size != 0) { auto NextRecord = this->operator*(); + if (!NextRecord) { + // NULL record pointer, don't attempt to proceed. Setting size to 0 will + // make this iterator compare equal to the end iterator. + this->Size = 0; + return; + } auto NextSize = Self::getCurrentRecordSize(NextRecord); if (NextSize > Size) { std::cerr << "!!! Reflection section too small to contain first record\n" << std::endl; @@ -109,7 +115,9 @@ class ReflectionSectionIteratorBase << ", size of first record: " << NextSize << std::endl; - abort(); + // Set this iterator equal to the end. This section is effectively + // empty. + this->Size = 0; } } } @@ -149,7 +157,7 @@ class ReflectionSectionIteratorBase std::cerr << std::hex << std::setw(2) << (int)p[i] << " "; } std::cerr << std::endl; - abort(); + Size = 0; // Set this iterator equal to the end. } } @@ -157,6 +165,10 @@ class ReflectionSectionIteratorBase } bool operator==(const Self &other) const { + // Size = 0 means we're at the end even if Cur doesn't match. This allows + // iterators that encounter an incorrect size to safely end iteration. + if (Size == 0 && other.Size == 0) + return true; return Cur == other.Cur && Size == other.Size; }