1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <vector>
bool Bool();
void MergeWithDifferentContainerValuesIteratorUnchecked() {
std::vector<int> v1 = {1, 10, 100};
std::vector<int> v2 = {1, 10, 100};
std::vector<int> v3 = {1, 10, 100};
auto it = std::find(v1.begin(), v1.end(), 10);
if (Bool()) {
it = std::find(v2.begin(), v2.end(), 10);
} else {
it = std::find(v3.begin(), v3.end(), 10);
}
v1.clear();
// As for now, the tool doesn't handle well merges with different container
// values. see https://crbug.com/1455371.
// However, since the iterator was never checked against `end`, accessing it
// is still considered invalid.
*it = 20;
}
void MergeWithDifferentContainerValueIteratorChecked() {
std::vector<int> v1 = {1, 10, 100};
std::vector<int> v2 = {1, 10, 100};
std::vector<int> v3 = {1, 10, 100};
auto it = std::find(v1.begin(), v1.end(), 10);
if (Bool()) {
it = std::find(v2.begin(), v2.end(), 10);
if (it == std::end(v2)) {
return;
}
} else {
it = std::find(v3.begin(), v3.end(), 10);
if (it == std::end(v3)) {
return;
}
}
v1.clear();
// This is in practice valid, because it can only be true here.
// Although the tool does well on this case, the fact that multiple
// containers are being used for the same iterator above means that the tool
// is lucky.
*it = 20;
}
void MergeWithDifferentContainersInvalidateAll() {
std::vector<int> v1 = {1, 10, 100};
std::vector<int> v2 = {1, 10, 100};
auto it = std::find(v1.begin(), v1.end(), 10);
if (Bool()) {
it = std::find(v2.begin(), v2.end(), 10);
if (it == std::end(v2)) {
return;
}
} else {
it = std::find(v1.begin(), v1.end(), 10);
if (it == std::end(v1)) {
return;
}
}
v1.clear();
// It is invalid because the iterator could still point to `v1`, which is
// invalidated by `v1.clear()`.
*it = 20;
}
void MergeWithSameContainerValueIteratorChecked() {
std::vector<int> v1 = {1, 10, 100};
std::vector<int> v2 = {1, 10, 100};
std::vector<int> v3 = {1, 10, 100};
auto it = std::find(v1.begin(), v1.end(), 10);
if (Bool()) {
it = std::find(v1.begin(), v1.end(), 10);
if (it == std::end(v1)) {
return;
}
} else {
it = std::find(v1.begin(), v1.end(), 10);
if (it == std::end(v1)) {
return;
}
}
// It is valid here because we would have returned from the function in the
// previous conditional blocks if not.
*it;
v1.clear();
// It just got invalidated by `v1.clear()`.
*it = 20;
}
|