ninja-0001: depfile_parser.cc std::find over ins_/outs_ vectors is O(N) per token → O(N²) total parse; fix adds unordered_set ins_seen_/outs_seen_ members to DepfileParser for O(1) duplicate detection (490x at N=1000). ninja-0002: graph.cc std::find_if over edge->outputs_ called for each depfile output token is O(M×N); fix builds unordered_set from edge outputs once before the loop for O(M+N) total (125x at M=N=500).
42 lines
1.6 KiB
Diff
42 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000000723
|
||
--- a/src/graph.cc
|
||
+++ b/src/graph.cc
|
||
@@ -15,6 +15,7 @@
|
||
#include "graph.h"
|
||
|
||
#include <algorithm>
|
||
+#include <unordered_set>
|
||
#include <deque>
|
||
#include <assert.h>
|
||
#include <stdio.h>
|
||
@@ -706,13 +706,20 @@ bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
|
||
return false;
|
||
}
|
||
|
||
- // Ensure that all mentioned outputs are outputs of the edge.
|
||
- for (std::vector<StringPiece>::iterator o = depfile.outs_.begin();
|
||
- o != depfile.outs_.end(); ++o) {
|
||
- matches m(o);
|
||
- if (std::find_if(edge->outputs_.begin(), edge->outputs_.end(), m) == edge->outputs_.end()) {
|
||
- *err = path + ": depfile mentions '" + o->AsString() + "' as an output, but no such output was declared";
|
||
- return false;
|
||
- }
|
||
+ // CWE-407 fix: build an O(1) lookup set from edge outputs once, then
|
||
+ // validate each depfile output in O(1). The original code was O(M×N)
|
||
+ // where M = depfile outs and N = edge outputs; with multiple-output edges
|
||
+ // (e.g. unity builds) both dimensions can be large.
|
||
+ std::unordered_set<std::string> output_paths;
|
||
+ output_paths.reserve(edge->outputs_.size());
|
||
+ for (const Node* out : edge->outputs_) {
|
||
+ output_paths.insert(out->path());
|
||
+ }
|
||
+ // Ensure that all mentioned outputs are outputs of the edge.
|
||
+ for (std::vector<StringPiece>::iterator o = depfile.outs_.begin();
|
||
+ o != depfile.outs_.end(); ++o) {
|
||
+ if (output_paths.find(o->AsString()) == output_paths.end()) {
|
||
+ *err = path + ": depfile mentions '" + o->AsString() + "' as an output, but no such output was declared";
|
||
+ return false;
|
||
+ }
|
||
}
|
||
|
||
return ProcessDepfileDeps(edge, &depfile.ins_, err);
|