Skip to content

Commit 67220c2

Browse files
committed
[ORC] Fix serialization / deserialization of default-constructed ArrayRef<char>.
Avoids a zero-length memcpy from a null src, which caused errors on some of the sanitizer bots. Also uses null when deserializing an empty ArrayRef (rather than pointing to a zero length range in the middle of the input buffer).
1 parent 58dfaaa commit 67220c2

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

llvm/include/llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class SPSOutputBuffer {
5656
SPSOutputBuffer(char *Buffer, size_t Remaining)
5757
: Buffer(Buffer), Remaining(Remaining) {}
5858
bool write(const char *Data, size_t Size) {
59+
assert(Data && "Data must not be null");
5960
if (Size > Remaining)
6061
return false;
6162
memcpy(Buffer, Data, Size);
@@ -349,6 +350,8 @@ template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> {
349350
static bool serialize(SPSOutputBuffer &OB, const ArrayRef<char> &A) {
350351
if (!SPSArgList<uint64_t>::serialize(OB, static_cast<uint64_t>(A.size())))
351352
return false;
353+
if (A.empty()) // Empty ArrayRef may have null data, so bail out early.
354+
return true;
352355
return OB.write(A.data(), A.size());
353356
}
354357

@@ -358,7 +361,7 @@ template <> class SPSSerializationTraits<SPSSequence<char>, ArrayRef<char>> {
358361
return false;
359362
if (Size > std::numeric_limits<size_t>::max())
360363
return false;
361-
A = {IB.data(), static_cast<size_t>(Size)};
364+
A = {Size ? IB.data() : nullptr, static_cast<size_t>(Size)};
362365
return IB.skip(Size);
363366
}
364367
};

llvm/unittests/ExecutionEngine/Orc/SimplePackedSerializationTest.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,24 @@ TEST(SimplePackedSerializationTest, ArrayRef) {
187187
// Input should reference buffer.
188188
EXPECT_LT(HelloIn.data() - Buffer, BufferSize);
189189
}
190+
191+
TEST(SimplePackedSerializationTest, ArrayRefEmpty) {
192+
// Make sure that empty ArrayRefs serialize and deserialize as expected.
193+
// Empty ArrayRefs should not succeed even when the data field is null, and
194+
// should deserialize to a default-constructed ArrayRef, not a pointer into
195+
// the stream.
196+
constexpr unsigned BufferSize = sizeof(uint64_t);
197+
char Buffer[BufferSize];
198+
memset(Buffer, 0, BufferSize);
199+
200+
ArrayRef<char> AOut;
201+
SPSOutputBuffer OB(Buffer, BufferSize);
202+
EXPECT_TRUE(SPSArgList<SPSSequence<char>>::serialize(OB, AOut));
203+
204+
ArrayRef<char> AIn;
205+
SPSInputBuffer IB(Buffer, BufferSize);
206+
EXPECT_TRUE(SPSArgList<SPSSequence<char>>::deserialize(IB, AIn));
207+
208+
EXPECT_EQ(AIn.data(), nullptr);
209+
EXPECT_EQ(AIn.size(), 0U);
210+
}

0 commit comments

Comments
 (0)