Skip to content

Commit 4d1b1d7

Browse files
authored
[IRGen] Prevent overflow in RecordField with large explosions (#64828)
rdar://99415586 Exploding very large types could cause an overflow, which in turn caused a crash later in IRGen. Fixed by increasing width of the variables in question from 16 to 32 bit and adding an overflow check.
1 parent 57dc5a6 commit 4d1b1d7

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

include/swift/AST/DiagnosticsIRGen.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,8 @@ ERROR(temporary_allocation_alignment_not_positive,none,
5959
ERROR(temporary_allocation_alignment_not_power_of_2,none,
6060
"alignment value must be a power of two", ())
6161

62+
ERROR(explosion_size_oveflow,none,
63+
"explosion size too large", ())
64+
6265
#define UNDEFINE_DIAGNOSTIC_MACROS
6366
#include "DefineDiagnosticMacros.h"

lib/IRGen/GenRecord.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
#include "Outlining.h"
2929
#include "TypeInfo.h"
3030
#include "StructLayout.h"
31+
#include "llvm/Support/MathExtras.h"
3132
#include "llvm/Support/TrailingObjects.h"
33+
#include "swift/AST/DiagnosticsIRGen.h"
3234

3335
namespace swift {
3436
namespace irgen {
@@ -42,8 +44,8 @@ template <class FieldImpl> class RecordField {
4244
template <class, class, class> friend class RecordTypeBuilder;
4345

4446
/// Begin/End - the range of explosion indexes for this element
45-
unsigned Begin : 16;
46-
unsigned End : 16;
47+
unsigned Begin;
48+
unsigned End;
4749

4850
protected:
4951
explicit RecordField(const TypeInfo &elementTI)
@@ -883,7 +885,12 @@ class RecordTypeBuilder {
883885

884886
auto &fieldInfo = fields.back();
885887
fieldInfo.Begin = explosionSize;
886-
explosionSize += loadableFieldTI->getExplosionSize();
888+
bool overflow = false;
889+
explosionSize = llvm::SaturatingAdd(explosionSize, loadableFieldTI->getExplosionSize(), &overflow);
890+
if (overflow) {
891+
IGM.Context.Diags.diagnose(SourceLoc(), diag::explosion_size_oveflow);
892+
}
893+
887894
fieldInfo.End = explosionSize;
888895
}
889896

0 commit comments

Comments
 (0)