Avoid reading uninitialized end.p for point writes/reads
For point writes and point reads (end.len == 0), end.p is not part of the API contract and callers may leave it uninitialized -- both the C and C++ API smoke tests and the fuzz test driver do so. However, insertPointWritesOrSorted and check::Job::init unconditionally built a TrivialSpan from end.p, reading the uninitialized pointer even though it is never used for point operations. Move the end span construction into the range-write/range-read branches so end.p is only read when end.len > 0. This is semantically identical but removes the uninitialized reads that MemorySanitizer reports.
This commit is contained in:
+3
-4
@@ -3864,11 +3864,10 @@ PRESERVE_NONE void right_side_iter(Job *job, Context *context) {
|
|||||||
void Job::init(const ConflictSet::ReadRange *read, ConflictSet::Result *result,
|
void Job::init(const ConflictSet::ReadRange *read, ConflictSet::Result *result,
|
||||||
Node *root, int64_t oldestVersionFullPrecision) {
|
Node *root, int64_t oldestVersionFullPrecision) {
|
||||||
auto begin = TrivialSpan(read->begin.p, read->begin.len);
|
auto begin = TrivialSpan(read->begin.p, read->begin.len);
|
||||||
auto end = TrivialSpan(read->end.p, read->end.len);
|
|
||||||
if (read->readVersion < oldestVersionFullPrecision) [[unlikely]] {
|
if (read->readVersion < oldestVersionFullPrecision) [[unlikely]] {
|
||||||
*result = ConflictSet::TooOld;
|
*result = ConflictSet::TooOld;
|
||||||
continuation = complete;
|
continuation = complete;
|
||||||
} else if (end.size() == 0) {
|
} else if (read->end.len == 0) {
|
||||||
this->begin = begin;
|
this->begin = begin;
|
||||||
this->n = root;
|
this->n = root;
|
||||||
this->readVersion = InternalVersionT(read->readVersion);
|
this->readVersion = InternalVersionT(read->readVersion);
|
||||||
@@ -3876,7 +3875,7 @@ void Job::init(const ConflictSet::ReadRange *read, ConflictSet::Result *result,
|
|||||||
continuation = check::point_read_state_machine::begin;
|
continuation = check::point_read_state_machine::begin;
|
||||||
} else {
|
} else {
|
||||||
this->begin = begin;
|
this->begin = begin;
|
||||||
this->end = end;
|
this->end = TrivialSpan(read->end.p, read->end.len);
|
||||||
this->n = root;
|
this->n = root;
|
||||||
this->readVersion = InternalVersionT(read->readVersion);
|
this->readVersion = InternalVersionT(read->readVersion);
|
||||||
this->result = result;
|
this->result = result;
|
||||||
@@ -5046,8 +5045,8 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
const auto &w = writes[i];
|
const auto &w = writes[i];
|
||||||
auto begin = TrivialSpan(w.begin.p, w.begin.len);
|
auto begin = TrivialSpan(w.begin.p, w.begin.len);
|
||||||
auto end = TrivialSpan(w.end.p, w.end.len);
|
|
||||||
if (w.end.len > 0) {
|
if (w.end.len > 0) {
|
||||||
|
auto end = TrivialSpan(w.end.p, w.end.len);
|
||||||
addWriteRange(rootParent->children[0], begin, end,
|
addWriteRange(rootParent->children[0], begin, end,
|
||||||
InternalVersionT(writeVersion), &writeContext);
|
InternalVersionT(writeVersion), &writeContext);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user