20
20
21
21
#if SWIFT_ENABLE_REFLECTION
22
22
23
+ #include " llvm/Support/MathExtras.h"
23
24
#include " swift/ABI/Enum.h"
24
25
#include " swift/ABI/MetadataValues.h"
25
26
#include " swift/Reflection/TypeLowering.h"
@@ -645,6 +646,8 @@ class SimpleMultiPayloadEnumTypeInfo: public EnumTypeInfo {
645
646
// A variable-length bitmap used to track "spare bits" for general multi-payload
646
647
// enums.
647
648
class BitMask {
649
+ static constexpr unsigned maxSize = 128 * 1024 * 1024 ; // 128MB
650
+
648
651
unsigned size; // Size of mask in bytes
649
652
uint8_t *mask;
650
653
public:
@@ -654,18 +657,72 @@ class BitMask {
654
657
// Construct a bitmask of the appropriate number of bytes
655
658
// initialized to all bits set
656
659
BitMask (unsigned sizeInBytes): size(sizeInBytes) {
657
- assert (sizeInBytes < std::numeric_limits<uint32_t >::max ());
660
+ // Gracefully fail by constructing an empty mask if we exceed the size
661
+ // limit.
662
+ if (size > maxSize) {
663
+ size = 0 ;
664
+ mask = nullptr ;
665
+ return ;
666
+ }
667
+
658
668
mask = (uint8_t *)malloc (size);
669
+
670
+ if (!mask) {
671
+ // Malloc might fail if size is large due to some bad data. Assert in
672
+ // asserts builds, and fail gracefully in non-asserts builds by
673
+ // constructing an empty BitMask.
674
+ assert (false && " Failed to allocate BitMask" );
675
+ size = 0 ;
676
+ return ;
677
+ }
678
+
659
679
memset (mask, 0xff , size);
660
680
}
661
681
// Construct a bitmask of the appropriate number of bytes
662
682
// initialized with bits from the specified buffer
663
- BitMask (unsigned sizeInBytes, const uint8_t *initialValue, unsigned initialValueBytes, unsigned offset)
664
- : size(sizeInBytes)
665
- {
666
- assert (sizeInBytes < std::numeric_limits<uint32_t >::max ());
667
- assert (initialValueBytes + offset <= sizeInBytes);
683
+ BitMask (unsigned sizeInBytes, const uint8_t *initialValue,
684
+ unsigned initialValueBytes, unsigned offset)
685
+ : size(sizeInBytes) {
686
+ // Gracefully fail by constructing an empty mask if we exceed the size
687
+ // limit.
688
+ if (size > maxSize) {
689
+ size = 0 ;
690
+ mask = nullptr ;
691
+ return ;
692
+ }
693
+
694
+ // Bad data could cause the initial value location to be off the end of our
695
+ // size. If initialValueBytes + offset is beyond sizeInBytes (or overflows),
696
+ // assert in asserts builds, and fail gracefully in non-asserts builds by
697
+ // constructing an empty BitMask.
698
+ bool overflowed = false ;
699
+ unsigned initialValueEnd =
700
+ llvm::SaturatingAdd (initialValueBytes, offset, &overflowed);
701
+ if (overflowed) {
702
+ assert (false && " initialValueBytes + offset overflowed" );
703
+ size = 0 ;
704
+ mask = nullptr ;
705
+ return ;
706
+ }
707
+ assert (initialValueEnd <= sizeInBytes);
708
+ if (initialValueEnd > size) {
709
+ assert (false && " initialValueBytes + offset is greater than size" );
710
+ size = 0 ;
711
+ mask = nullptr ;
712
+ return ;
713
+ }
714
+
668
715
mask = (uint8_t *)calloc (1 , size);
716
+
717
+ if (!mask) {
718
+ // Malloc might fail if size is large due to some bad data. Assert in
719
+ // asserts builds, and fail gracefully in non-asserts builds by
720
+ // constructing an empty BitMask.
721
+ assert (false && " Failed to allocate BitMask" );
722
+ size = 0 ;
723
+ return ;
724
+ }
725
+
669
726
memcpy (mask + offset, initialValue, initialValueBytes);
670
727
}
671
728
// Move constructor moves ownership and zeros the src
@@ -864,10 +921,12 @@ class BitMask {
864
921
865
922
void andNotMask (void *maskData, unsigned len, unsigned offset) {
866
923
assert (offset < size);
867
- unsigned common = std::min (len, size - offset);
868
- uint8_t *maskBytes = (uint8_t *)maskData;
869
- for (unsigned i = 0 ; i < common; ++i) {
870
- mask[i + offset] &= ~maskBytes[i];
924
+ if (offset < size) {
925
+ unsigned common = std::min (len, size - offset);
926
+ uint8_t *maskBytes = (uint8_t *)maskData;
927
+ for (unsigned i = 0 ; i < common; ++i) {
928
+ mask[i + offset] &= ~maskBytes[i];
929
+ }
871
930
}
872
931
}
873
932
};
0 commit comments