Skip to content

Commit 19d8768

Browse files
network: Fix NixVector deserialization and Packet::Deserialize size accounting for padded sections
1 parent 29e6cd6 commit 19d8768

4 files changed

Lines changed: 103 additions & 50 deletions

File tree

src/network/model/nix-vector.cc

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,17 @@ NixVector::Deserialize(const uint32_t* buffer, uint32_t size)
235235
NS_LOG_FUNCTION(this << buffer << size);
236236
const uint32_t* p = buffer;
237237

238-
NS_ASSERT_MSG(size >= sizeof(m_totalBitSize),
239-
"NixVector minimum serialized length is " << sizeof(m_totalBitSize) << " bytes");
240-
if (size < sizeof(m_totalBitSize))
238+
// Widths of the serialized fields: total number of bits in the nix-vector
239+
// (always present), number of used bits, epoch, and each 32-bit word of
240+
// neighbor indices (only present when the nix-vector is not empty)
241+
constexpr uint32_t totalBitSizeFieldBytes = sizeof(m_totalBitSize);
242+
constexpr uint32_t usedFieldBytes = sizeof(m_used);
243+
constexpr uint32_t epochFieldBytes = sizeof(m_epoch);
244+
constexpr uint32_t nixWordBytes = sizeof(uint32_t);
245+
246+
NS_ASSERT_MSG(size >= totalBitSizeFieldBytes,
247+
"NixVector minimum serialized length is " << totalBitSizeFieldBytes << " bytes");
248+
if (size < totalBitSizeFieldBytes)
241249
{
242250
// return zero if an entire nix-vector was
243251
// not deserialized
@@ -248,22 +256,24 @@ NixVector::Deserialize(const uint32_t* buffer, uint32_t size)
248256

249257
if (m_totalBitSize)
250258
{
251-
m_used = *p++;
252-
253259
// NixVector is packed in 32-bit unsigned ints.
254260
uint32_t nixVectorLength = m_totalBitSize / 32;
255261
nixVectorLength += (m_totalBitSize % 32) ? 1 : 0;
256262

257-
NS_ASSERT_MSG(size >= 16 + nixVectorLength,
258-
"NixVector serialized length should have been " << 16 + nixVectorLength
263+
const uint32_t expectedSize = totalBitSizeFieldBytes + usedFieldBytes + epochFieldBytes +
264+
nixVectorLength * nixWordBytes;
265+
NS_ASSERT_MSG(size >= expectedSize,
266+
"NixVector serialized length should have been " << expectedSize
259267
<< " but buffer is shorter");
260-
if (size < 16 + nixVectorLength * 4)
268+
if (size < expectedSize)
261269
{
262270
// return zero if an entire nix-vector was
263271
// not deserialized
264272
return 0;
265273
}
266274

275+
m_used = *p++;
276+
267277
// make sure the nix-vector
268278
// is empty
269279
m_nixVector.clear();

src/network/model/nix-vector.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class NixVector : public SimpleRefCount<NixVector>
124124
*
125125
* @param buffer points to buffer for deserialization
126126
* @param size number of bytes to deserialize
127-
* @return number of deerialized bytes on success, 0 on failure
127+
* @return number of deserialized bytes on success, 0 on failure
128128
*/
129129
uint32_t Deserialize(const uint32_t* buffer, uint32_t size);
130130

src/network/model/packet.cc

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ Packet::Packet(const uint8_t* buffer, uint32_t size, bool magic)
189189
m_nixVector(nullptr)
190190
{
191191
NS_ASSERT(magic);
192-
Deserialize(buffer, size);
192+
[[maybe_unused]] uint32_t deserialized = Deserialize(buffer, size);
193+
NS_ASSERT_MSG(deserialized == size, "Packet deserialization failed");
193194
}
194195

195196
Packet::Packet(const uint8_t* buffer, uint32_t size)
@@ -595,6 +596,28 @@ Packet::EnableChecking()
595596
PacketMetadata::EnableChecking();
596597
}
597598

599+
namespace
600+
{
601+
602+
/// Bytes occupied by the length prefix word that precedes each serialized section.
603+
constexpr uint32_t SECTION_LENGTH_FIELD_SIZE = sizeof(uint32_t);
604+
605+
/// Serialized sections are padded so that each one starts on a 4-byte boundary.
606+
constexpr uint32_t SERIALIZATION_ALIGNMENT = sizeof(uint32_t);
607+
608+
/**
609+
* @brief Round a byte count up to the next serialization boundary.
610+
* @param bytes the unpadded byte count
611+
* @return bytes rounded up to a multiple of SERIALIZATION_ALIGNMENT
612+
*/
613+
constexpr uint32_t
614+
AlignToBoundary(uint32_t bytes)
615+
{
616+
return (bytes + SERIALIZATION_ALIGNMENT - 1) & ~(SERIALIZATION_ALIGNMENT - 1);
617+
}
618+
619+
} // namespace
620+
598621
uint32_t
599622
Packet::GetSerializedSize() const
600623
{
@@ -604,46 +627,46 @@ Packet::GetSerializedSize() const
604627
{
605628
// increment total size by the size of the nix-vector
606629
// ensuring 4-byte boundary
607-
size += ((m_nixVector->GetSerializedSize() + 3) & (~3));
630+
size += AlignToBoundary(m_nixVector->GetSerializedSize());
608631

609632
// add 4-bytes for entry of total length of nix-vector
610-
size += 4;
633+
size += SECTION_LENGTH_FIELD_SIZE;
611634
}
612635
else
613636
{
614637
// if no nix-vector, still have to add 4-bytes
615638
// to account for the entry of total size for
616639
// nix-vector in the buffer
617-
size += 4;
640+
size += SECTION_LENGTH_FIELD_SIZE;
618641
}
619642

620643
// increment total size by size of packet tag list
621644
// ensuring 4-byte boundary
622-
size += ((m_packetTagList.GetSerializedSize() + 3) & (~3));
645+
size += AlignToBoundary(m_packetTagList.GetSerializedSize());
623646

624647
// add 4-bytes for entry of total length of packet tag list
625-
size += 4;
648+
size += SECTION_LENGTH_FIELD_SIZE;
626649

627650
// increment total size by size of byte tag list
628651
// ensuring 4-byte boundary
629-
size += ((m_byteTagList.GetSerializedSize() + 3) & (~3));
652+
size += AlignToBoundary(m_byteTagList.GetSerializedSize());
630653

631654
// add 4-bytes for entry of total length of byte tag list
632-
size += 4;
655+
size += SECTION_LENGTH_FIELD_SIZE;
633656

634657
// increment total size by size of meta-data
635658
// ensuring 4-byte boundary
636-
size += ((m_metadata.GetSerializedSize() + 3) & (~3));
659+
size += AlignToBoundary(m_metadata.GetSerializedSize());
637660

638661
// add 4-bytes for entry of total length of meta-data
639-
size += 4;
662+
size += SECTION_LENGTH_FIELD_SIZE;
640663

641664
// increment total size by size of buffer
642665
// ensuring 4-byte boundary
643-
size += ((m_buffer.GetSerializedSize() + 3) & (~3));
666+
size += AlignToBoundary(m_buffer.GetSerializedSize());
644667

645668
// add 4-bytes for entry of total length of buffer
646-
size += 4;
669+
size += SECTION_LENGTH_FIELD_SIZE;
647670

648671
return size;
649672
}
@@ -658,15 +681,14 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
658681
if (m_nixVector)
659682
{
660683
uint32_t nixSize = m_nixVector->GetSerializedSize();
661-
size += nixSize;
684+
size += AlignToBoundary(nixSize) + SECTION_LENGTH_FIELD_SIZE;
662685
if (size > maxSize)
663686
{
664687
return 0;
665688
}
666689

667690
// put the total length of nix-vector in the buffer
668691
*p++ = nixSize;
669-
size += 4;
670692

671693
// serialize the nix-vector
672694
uint32_t serialized = m_nixVector->Serialize(p, nixSize);
@@ -677,11 +699,11 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
677699

678700
// increment p by nixSize bytes
679701
// ensuring 4-byte boundary
680-
p += ((nixSize + 3) & (~3)) / 4;
702+
p += AlignToBoundary(nixSize) / SERIALIZATION_ALIGNMENT;
681703
}
682704
else
683705
{
684-
size += 4;
706+
size += SECTION_LENGTH_FIELD_SIZE;
685707
if (size > maxSize)
686708
{
687709
return 0;
@@ -693,15 +715,14 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
693715

694716
// Serialize byte tag list
695717
uint32_t byteTagSize = m_byteTagList.GetSerializedSize();
696-
size += byteTagSize;
718+
size += AlignToBoundary(byteTagSize) + SECTION_LENGTH_FIELD_SIZE;
697719
if (size > maxSize)
698720
{
699721
return 0;
700722
}
701723

702724
// put the total length of byte tag list in the buffer
703725
*p++ = byteTagSize;
704-
size += 4;
705726

706727
// serialize the byte tag list
707728
uint32_t serialized = m_byteTagList.Serialize(p, byteTagSize);
@@ -712,19 +733,18 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
712733

713734
// increment p by byteTagSize bytes
714735
// ensuring 4-byte boundary
715-
p += ((byteTagSize + 3) & (~3)) / 4;
736+
p += AlignToBoundary(byteTagSize) / SERIALIZATION_ALIGNMENT;
716737

717738
// Serialize packet tag list
718739
uint32_t packetTagSize = m_packetTagList.GetSerializedSize();
719-
size += packetTagSize;
740+
size += AlignToBoundary(packetTagSize) + SECTION_LENGTH_FIELD_SIZE;
720741
if (size > maxSize)
721742
{
722743
return 0;
723744
}
724745

725746
// put the total length of packet tag list in the buffer
726747
*p++ = packetTagSize;
727-
size += 4;
728748

729749
// serialize the packet tag list
730750
serialized = m_packetTagList.Serialize(p, packetTagSize);
@@ -735,19 +755,18 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
735755

736756
// increment p by packetTagSize bytes
737757
// ensuring 4-byte boundary
738-
p += ((packetTagSize + 3) & (~3)) / 4;
758+
p += AlignToBoundary(packetTagSize) / SERIALIZATION_ALIGNMENT;
739759

740760
// Serialize Metadata
741761
uint32_t metaSize = m_metadata.GetSerializedSize();
742-
size += metaSize;
762+
size += AlignToBoundary(metaSize) + SECTION_LENGTH_FIELD_SIZE;
743763
if (size > maxSize)
744764
{
745765
return 0;
746766
}
747767

748768
// put the total length of metadata in the buffer
749769
*p++ = metaSize;
750-
size += 4;
751770

752771
// serialize the metadata
753772
serialized = m_metadata.Serialize(reinterpret_cast<uint8_t*>(p), metaSize);
@@ -758,11 +777,11 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
758777

759778
// increment p by metaSize bytes
760779
// ensuring 4-byte boundary
761-
p += ((metaSize + 3) & (~3)) / 4;
780+
p += AlignToBoundary(metaSize) / SERIALIZATION_ALIGNMENT;
762781

763782
// Serialize the packet contents
764783
uint32_t bufSize = m_buffer.GetSerializedSize();
765-
size += bufSize;
784+
size += AlignToBoundary(bufSize) + SECTION_LENGTH_FIELD_SIZE;
766785
if (size > maxSize)
767786
{
768787
return 0;
@@ -777,7 +796,7 @@ Packet::Serialize(uint8_t* buffer, uint32_t maxSize) const
777796
{
778797
return 0;
779798
}
780-
return size + bufSize + 4;
799+
return size;
781800
}
782801

783802
uint32_t
@@ -794,7 +813,7 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
794813

795814
// if sizeCheck less than nixSize, the buffer
796815
// will be overrun, assert
797-
NS_ASSERT(sizeCheck >= nixSize);
816+
NS_ASSERT(sizeCheck >= AlignToBoundary(nixSize) + SECTION_LENGTH_FIELD_SIZE);
798817

799818
if (nixSize > 0)
800819
{
@@ -809,16 +828,16 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
809828
m_nixVector = nix;
810829
// increment p by nixSize ensuring
811830
// 4-byte boundary
812-
p += (((nixSize + 3) & (~3)) / 4);
831+
p += AlignToBoundary(nixSize) / SERIALIZATION_ALIGNMENT;
813832
}
814-
sizeCheck -= nixSize + 4;
833+
sizeCheck -= AlignToBoundary(nixSize) + SECTION_LENGTH_FIELD_SIZE;
815834

816835
// read byte tags
817836
uint32_t byteTagSize = *p++;
818837

819838
// if sizeCheck less than byteTagSize, the buffer
820839
// will be overrun, assert
821-
NS_ASSERT(sizeCheck >= byteTagSize);
840+
NS_ASSERT(sizeCheck >= AlignToBoundary(byteTagSize) + SECTION_LENGTH_FIELD_SIZE);
822841

823842
uint32_t byteTagDeserialized = m_byteTagList.Deserialize(p, byteTagSize);
824843
if (!byteTagDeserialized)
@@ -828,15 +847,15 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
828847
}
829848
// increment p by byteTagSize ensuring
830849
// 4-byte boundary
831-
p += (((byteTagSize + 3) & (~3)) / 4);
832-
sizeCheck -= byteTagSize + 4;
850+
p += AlignToBoundary(byteTagSize) / SERIALIZATION_ALIGNMENT;
851+
sizeCheck -= AlignToBoundary(byteTagSize) + SECTION_LENGTH_FIELD_SIZE;
833852

834853
// read packet tags
835854
uint32_t packetTagSize = *p++;
836855

837856
// if sizeCheck less than packetTagSize, the buffer
838857
// will be overrun, assert
839-
NS_ASSERT(sizeCheck >= packetTagSize);
858+
NS_ASSERT(sizeCheck >= AlignToBoundary(packetTagSize) + SECTION_LENGTH_FIELD_SIZE);
840859

841860
uint32_t packetTagDeserialized = m_packetTagList.Deserialize(p, packetTagSize);
842861
if (!packetTagDeserialized)
@@ -846,15 +865,15 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
846865
}
847866
// increment p by packetTagSize ensuring
848867
// 4-byte boundary
849-
p += (((packetTagSize + 3) & (~3)) / 4);
850-
sizeCheck -= packetTagSize + 4;
868+
p += AlignToBoundary(packetTagSize) / SERIALIZATION_ALIGNMENT;
869+
sizeCheck -= AlignToBoundary(packetTagSize) + SECTION_LENGTH_FIELD_SIZE;
851870

852871
// read metadata
853872
uint32_t metaSize = *p++;
854873

855874
// if sizeCheck less than metaSize, the buffer
856875
// will be overrun, assert
857-
NS_ASSERT(sizeCheck >= metaSize);
876+
NS_ASSERT(sizeCheck >= AlignToBoundary(metaSize) + SECTION_LENGTH_FIELD_SIZE);
858877

859878
uint32_t metadataDeserialized =
860879
m_metadata.Deserialize(reinterpret_cast<const uint8_t*>(p), metaSize);
@@ -866,15 +885,15 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
866885
}
867886
// increment p by metaSize ensuring
868887
// 4-byte boundary
869-
p += (((metaSize + 3) & (~3)) / 4);
870-
sizeCheck -= metaSize + 4;
888+
p += AlignToBoundary(metaSize) / SERIALIZATION_ALIGNMENT;
889+
sizeCheck -= AlignToBoundary(metaSize) + SECTION_LENGTH_FIELD_SIZE;
871890

872891
// read buffer contents
873892
uint32_t bufSize = *p++;
874893

875894
// if sizeCheck less than bufSize, the buffer
876895
// will be overrun, assert
877-
NS_ASSERT(sizeCheck >= bufSize);
896+
NS_ASSERT(sizeCheck >= AlignToBoundary(bufSize) + SECTION_LENGTH_FIELD_SIZE);
878897

879898
uint32_t bufferDeserialized =
880899
m_buffer.Deserialize(reinterpret_cast<const uint8_t*>(p), bufSize);
@@ -884,7 +903,7 @@ Packet::Deserialize(const uint8_t* buffer, uint32_t size)
884903
// completely
885904
return 0;
886905
}
887-
sizeCheck -= bufSize + 4;
906+
sizeCheck -= AlignToBoundary(bufSize) + SECTION_LENGTH_FIELD_SIZE;
888907

889908
// return zero if did not deserialize the
890909
// number of expected bytes

0 commit comments

Comments
 (0)