mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-17 00:28:31 +09:00
[Fix] (MG_Remote, Wire): let an encoder caller omit a tail whose own count is zero - Count == 0 is a legal record for every kVarTail row and a required placeholder entry would be a trap
This commit is contained in:
@@ -672,14 +672,20 @@ namespace MobileGL::MG_Remote::Wire {
|
|||||||
// The caller's tails are held to the layout the PAYLOAD declares, which is the same
|
// The caller's tails are held to the layout the PAYLOAD declares, which is the same
|
||||||
// arithmetic the decoder will run. A Count that says 4000 while the tail holds 8 bytes
|
// arithmetic the decoder will run. A Count that says 4000 while the tail holds 8 bytes
|
||||||
// dies here, on the producing side, rather than on a peer that can only say "corrupt".
|
// dies here, on the producing side, rather than on a peer that can only say "corrupt".
|
||||||
if (tailCount != layout.TailCount) {
|
//
|
||||||
|
// A caller may SUPPLY FEWER TAILS THAN THE LAYOUT HAS, but only while the ones it left
|
||||||
|
// out are empty - Count == 0 is a legal record for every kVarTail row, and requiring a
|
||||||
|
// {nullptr, 0} entry for it would be a trap rather than a check. Anything else is a
|
||||||
|
// disagreement between the counts the payload declares and the bytes the caller holds.
|
||||||
|
if (tailCount > layout.TailCount) {
|
||||||
WireProtocolFatalAt("EncodeRecord.tailCount", tailCount, layout.TailCount);
|
WireProtocolFatalAt("EncodeRecord.tailCount", tailCount, layout.TailCount);
|
||||||
}
|
}
|
||||||
for (Uint32 i = 0; i < tailCount; ++i) {
|
for (Uint32 i = 0; i < layout.TailCount; ++i) {
|
||||||
if (tails[i].Size != layout.TailBytes[i]) {
|
const Uint64 supplied = i < tailCount ? tails[i].Size : 0;
|
||||||
WireProtocolFatalAt("EncodeRecord.tailBytes", tails[i].Size, layout.TailBytes[i]);
|
if (supplied != layout.TailBytes[i]) {
|
||||||
|
WireProtocolFatalAt("EncodeRecord.tailBytes", supplied, layout.TailBytes[i]);
|
||||||
}
|
}
|
||||||
if (tails[i].Size != 0 && tails[i].Bytes == nullptr) {
|
if (supplied != 0 && tails[i].Bytes == nullptr) {
|
||||||
WireProtocolFatal("EncodeRecord.tail", "non-zero tail length with a null pointer");
|
WireProtocolFatal("EncodeRecord.tail", "non-zero tail length with a null pointer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,6 +452,27 @@ TEST_F(PipeWireCodecTest, KVarTailRoundTripsWithItsTailIntact) {
|
|||||||
EXPECT_TRUE(applied);
|
EXPECT_TRUE(applied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PipeWireCodecTest, AnEmptyVarTailIsALegalRecordAndNeedsNoPlaceholderEntry) {
|
||||||
|
// Count == 0 is legal for every kVarTail row - "bind nothing at this range" - and a caller
|
||||||
|
// that had to pass a {nullptr, 0} entry for each absent tail would be walking into a trap
|
||||||
|
// rather than through a check. SetStreamOutputTargets is the sharpest case: its layout has
|
||||||
|
// TWO tails and both are empty at Count 0.
|
||||||
|
Wire2 wire;
|
||||||
|
MGPStreamOutputTargets header{};
|
||||||
|
header.Count = 0;
|
||||||
|
ASSERT_NE(wire.Encoder().EncodeRecord(MGPWireOp::SetStreamOutputTargets, &header, sizeof(header)),
|
||||||
|
kInvalidSeq);
|
||||||
|
MGPVertexBuffers buffers{};
|
||||||
|
buffers.Count = 0;
|
||||||
|
ASSERT_NE(wire.Encoder().EncodeRecord(MGPWireOp::SetVertexBuffers, &buffers, sizeof(buffers)),
|
||||||
|
kInvalidSeq);
|
||||||
|
bool applied = false;
|
||||||
|
ASSERT_TRUE(wire.PumpOne(&applied));
|
||||||
|
EXPECT_FALSE(applied); // no applier for stream output; off the reduced path
|
||||||
|
ASSERT_TRUE(wire.PumpOne(&applied));
|
||||||
|
EXPECT_TRUE(applied);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PipeWireCodecTest, KReplySlotMapPersistentIsAConstantDecline) {
|
TEST_F(PipeWireCodecTest, KReplySlotMapPersistentIsAConstantDecline) {
|
||||||
// R-6 / R-2.4. DECLINED is a real answer, not a failure, and the applier is not called at
|
// R-6 / R-2.4. DECLINED is a real answer, not a failure, and the applier is not called at
|
||||||
// all: the record's payload is a bare MGPHandleOnly and carries NEITHER the size NOR the
|
// all: the record's payload is a bare MGPHandleOnly and carries NEITHER the size NOR the
|
||||||
|
|||||||
Reference in New Issue
Block a user