Commit 0d9c2fc7 by Abseil Team Committed by Copybara-Service

Replace signed integer overflow, since that's undefined behavior, with unsigned integer overflow.

PiperOrigin-RevId: 648730502
Change-Id: I662c365c59be9e51f565fd215d284a96b7bd8743
parent f36d3331
...@@ -211,7 +211,7 @@ class NodeSet { ...@@ -211,7 +211,7 @@ class NodeSet {
Vec<int32_t> table_; Vec<int32_t> table_;
uint32_t occupied_; // Count of non-empty slots (includes deleted slots) uint32_t occupied_; // Count of non-empty slots (includes deleted slots)
static uint32_t Hash(int32_t a) { return static_cast<uint32_t>(a * 41); } static uint32_t Hash(int32_t a) { return static_cast<uint32_t>(a) * 41; }
// Return index for storing v. May return an empty index or deleted index // Return index for storing v. May return an empty index or deleted index
uint32_t FindIndex(int32_t v) const { uint32_t FindIndex(int32_t v) const {
...@@ -365,6 +365,14 @@ static Node* FindNode(GraphCycles::Rep* rep, GraphId id) { ...@@ -365,6 +365,14 @@ static Node* FindNode(GraphCycles::Rep* rep, GraphId id) {
return (n->version == NodeVersion(id)) ? n : nullptr; return (n->version == NodeVersion(id)) ? n : nullptr;
} }
void GraphCycles::TestOnlyAddNodes(uint32_t n) {
uint32_t old_size = rep_->nodes_.size();
rep_->nodes_.resize(n);
for (auto i = old_size; i < n; ++i) {
rep_->nodes_[i] = nullptr;
}
}
GraphCycles::GraphCycles() { GraphCycles::GraphCycles() {
InitArenaIfNecessary(); InitArenaIfNecessary();
rep_ = new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Rep), arena)) rep_ = new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Rep), arena))
...@@ -373,6 +381,7 @@ GraphCycles::GraphCycles() { ...@@ -373,6 +381,7 @@ GraphCycles::GraphCycles() {
GraphCycles::~GraphCycles() { GraphCycles::~GraphCycles() {
for (auto* node : rep_->nodes_) { for (auto* node : rep_->nodes_) {
if (node == nullptr) { continue; }
node->Node::~Node(); node->Node::~Node();
base_internal::LowLevelAlloc::Free(node); base_internal::LowLevelAlloc::Free(node);
} }
......
...@@ -126,6 +126,11 @@ class GraphCycles { ...@@ -126,6 +126,11 @@ class GraphCycles {
// Expensive: should only be called from graphcycles_test.cc. // Expensive: should only be called from graphcycles_test.cc.
bool CheckInvariants() const; bool CheckInvariants() const;
// Test-only method to add more nodes. The nodes will not be valid, and this
// method should only be used to test the behavior of the graph when it is
// very full.
void TestOnlyAddNodes(uint32_t n);
// ---------------------------------------------------- // ----------------------------------------------------
struct Rep; struct Rep;
private: private:
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "absl/synchronization/internal/graphcycles.h" #include "absl/synchronization/internal/graphcycles.h"
#include <climits>
#include <map> #include <map>
#include <random> #include <random>
#include <unordered_set> #include <unordered_set>
...@@ -458,6 +459,24 @@ TEST_F(GraphCyclesTest, ManyEdges) { ...@@ -458,6 +459,24 @@ TEST_F(GraphCyclesTest, ManyEdges) {
CheckInvariants(g_); CheckInvariants(g_);
} }
TEST(GraphCycles, IntegerOverflow) {
GraphCycles graph_cycles;
char *buf = (char *)nullptr;
GraphId prev_id = graph_cycles.GetId(buf);
buf += 1;
GraphId id = graph_cycles.GetId(buf);
ASSERT_TRUE(graph_cycles.InsertEdge(prev_id, id));
// INT_MAX / 40 is enough to cause an overflow when multiplied by 41.
graph_cycles.TestOnlyAddNodes(INT_MAX / 40);
buf += 1;
GraphId newid = graph_cycles.GetId(buf);
graph_cycles.HasEdge(prev_id, newid);
graph_cycles.RemoveNode(buf);
}
} // namespace synchronization_internal } // namespace synchronization_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment