From 737209737635fdec716ac5ba6e59042060dd846e Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Thu, 18 Jan 2024 14:23:29 -0800 Subject: [PATCH 1/2] base: fix Integer overflow in AddrRange bug An issue raised in #240 where if an address range ends at the last byte of a 64 bit address space, it will be considered a subset of any other address range that starts at the first byte of the range. Change-Id: I517f4717052eda2504de971be0eb59ee9a623dd3 --- src/base/addr_range.hh | 13 ++++++++++++- src/base/addr_range.test.cc | 13 +++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/base/addr_range.hh b/src/base/addr_range.hh index 11fb1cd668..aa1cb6ae2a 100644 --- a/src/base/addr_range.hh +++ b/src/base/addr_range.hh @@ -455,7 +455,18 @@ class AddrRange return r.contains(_start) && r.contains(_end - 1) && size() <= r.granularity(); } else { - return _start >= r._start && _end <= r._end; + + if (_end <= _start){ + // Special case: if our range wraps around that is + // _end is 2^64 so it wraps to 0. + // In this case r will be a subset only if its _end + // also wraps around. + return _start >= r._start && r._end == 0; + } else { + // Normal case: Check if our range is completely within 'r'. + return _start >= r._start && _end <= r._end; + } + } } diff --git a/src/base/addr_range.test.cc b/src/base/addr_range.test.cc index 1e861544ff..f1a454ff5f 100644 --- a/src/base/addr_range.test.cc +++ b/src/base/addr_range.test.cc @@ -1544,6 +1544,19 @@ TEST(AddrRangeTest, SubtractionAssignmentOfRangeListFromRangeList) expected_range3, expected_range4)); } +TEST(AddrRangeTest, isNotSubsetLastByte) +{ + /* An issue raised in https://github.com/gem5/gem5/issues/240 where if an + * address range ends at the last byte of a 64 bit address space, it will + * be considered a subset of any other address range that starts at the + * first byte of the range. + */ + + AddrRange first_four_bytes = RangeSize(0x0, 4); + AddrRange last_four_bytes = RangeSize(0xfffffffffffffffc, 4); + + EXPECT_FALSE(last_four_bytes.isSubset(first_four_bytes)); +} /* * InterleavingRanges: * The exclude method does not support interleaving ranges From 78613e2307d55165d3b9418fd6341732ca938db5 Mon Sep 17 00:00:00 2001 From: Harshil Patel Date: Tue, 23 Jan 2024 11:35:54 -0800 Subject: [PATCH 2/2] base: Add a check for edge case - Now check for the condition where the bigger address range wraps but smaller does not. Change-Id: Icc7a549afaf82a277dc2845255aa1702a1d662e0 --- src/base/addr_range.hh | 9 ++++++++- src/base/addr_range.test.cc | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/base/addr_range.hh b/src/base/addr_range.hh index aa1cb6ae2a..d49ebf49b6 100644 --- a/src/base/addr_range.hh +++ b/src/base/addr_range.hh @@ -459,9 +459,16 @@ class AddrRange if (_end <= _start){ // Special case: if our range wraps around that is // _end is 2^64 so it wraps to 0. - // In this case r will be a subset only if its _end + // In this case we will be a subset only if r._end // also wraps around. return _start >= r._start && r._end == 0; + } else if (r._end <= r._start){ + // Special case: if r wraps around that is + // r._end is 2^64 so it wraps to 0. + // In this case we will be a subset only if our _start + // is within r._start/ _end does not matter + // because r wraps around. + return _start >= r._start; } else { // Normal case: Check if our range is completely within 'r'. return _start >= r._start && _end <= r._end; diff --git a/src/base/addr_range.test.cc b/src/base/addr_range.test.cc index f1a454ff5f..eb7bed971a 100644 --- a/src/base/addr_range.test.cc +++ b/src/base/addr_range.test.cc @@ -1557,6 +1557,23 @@ TEST(AddrRangeTest, isNotSubsetLastByte) EXPECT_FALSE(last_four_bytes.isSubset(first_four_bytes)); } + +TEST(AddrRangeTest, isSubsetLastByte) +{ + /* An issue raised in https://github.com/gem5/gem5/issues/240 where if an + * address range ends at the last byte of a 64 bit address space, it will + * be considered a subset of any other address range that starts at the + * first byte of the range. + * + * This test checks it subset works correctly when the range is the last + * byte of the address space. + */ + AddrRange last_four_bytes = RangeSize(0xfffffffffffffffc, 4); + AddrRange not_wrapped_last_bytes = RangeSize(0xfffffffffffffffc, 3); + + EXPECT_TRUE(not_wrapped_last_bytes.isSubset(last_four_bytes)); +} + /* * InterleavingRanges: * The exclude method does not support interleaving ranges