Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/pci_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ std::vector<uint8_t> PciDataHandler::read(const uint32_t offset,
return {};
}

// Read up to regionSize in case the offset + length overflowed
// Clamp to the bytes remaining from offset. Comparing against the
// remaining space avoids the offset + length wraparound.
uint32_t finalLength =
(offset + length < regionSize) ? length : regionSize - offset;
(length < regionSize - offset) ? length : regionSize - offset;
std::vector<uint8_t> results(finalLength);

// Use a volatile pointer to ensure every access reads directly from the
Expand Down Expand Up @@ -73,16 +74,17 @@ uint32_t PciDataHandler::write(const uint32_t offset,
return 0;
}

// Write up to regionSize in case the offset + length overflowed
uint16_t finalLength =
(offset + length < regionSize) ? length : regionSize - offset;
// Clamp to the bytes remaining from offset. Comparing against the
// remaining space avoids the offset + length wraparound.
uint32_t finalLength =
(length < regionSize - offset) ? length : regionSize - offset;
// Use a volatile pointer to ensure every access writes directly to the
// memory-mapped region.
volatile uint8_t* dest =
reinterpret_cast<volatile uint8_t*>(data_ptr + offset);

// Perform a byte-by-byte copy to ensure volatile semantics.
for (uint16_t i = 0; i < finalLength; ++i)
for (uint32_t i = 0; i < finalLength; ++i)
{
dest[i] = bytes[i];
}
Expand Down
14 changes: 14 additions & 0 deletions test/pci_handler_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,19 @@ TEST_F(PciHandlerTest, WritePasses)
EXPECT_THAT(testMapped, ElementsAreArray(expectedMapped));
}

TEST(PciHandlerLargeRegion, WriteLengthIsNotTruncated)
{
// Region larger than 16 bits so the clamped length exceeds a uint16_t.
constexpr size_t regionSize = 0x10000 + 16;
std::vector<uint8_t> backing(regionSize, 0);
PciDataHandler pciDataHandler(backing.data(), regionSize);

std::vector<uint8_t> payload(regionSize, 0xab);
// The whole region is writable in one call; the returned count must cover
// every byte instead of wrapping at 16 bits.
EXPECT_EQ(pciDataHandler.write(0, payload), regionSize);
EXPECT_THAT(backing, ElementsAreArray(payload));
}

} // namespace
} // namespace bios_bmc_smm_error_logger