| // 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; |
| } |