Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 06:00 UTC
caddyfile: fix importGraph self-loop and stale-edge bugs (#7971)
- willCycle now reports a cycle when from == to, so addEdge rejects self-loops (a self-importing file was previously accepted). - removeNode now drops the removed node's outgoing edges and any incoming edges pointing at it, keeping the adjacency map consistent. Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>
Mohammed Al Sahaf committed
Sep 3, 2026 at 00:48 UTC
2cb7ebca45913da5824b7b2b4ef845d7e80da41d
2 files changed
+52
caddyconfig/caddyfile/importgraph.go
+7
@@ -44,6 +44,10 @@ func (i *importGraph) addNodes(names []string) {
44
45
func (i *importGraph) removeNode(name string) {
46
delete(i.nodes, name)
47
+ delete(i.edges, name)
48
+ for k, targets := range i.edges {
49
+ i.edges[k] = slices.DeleteFunc(targets, func(t string) bool { return t == name })
50
+ }
51
}
52
53
func (i *importGraph) removeNodes(names []string) {
@@ -96,6 +100,9 @@ func (i *importGraph) areConnected(from, to string) bool {
100
}
101
102
func (i *importGraph) willCycle(from, to string) bool {
103
+ if from == to {
104
+ return true
105
+ }
106
collector := make(map[string]bool)
107
108
var visit func(string)
caddyconfig/caddyfile/importgraph_test.go
new
+45
@@ -0,0 +1,45 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddyfile
16
+
17
+import "testing"
18
+
19
+func TestImportGraphSelfLoop(t *testing.T) {
20
+ g := &importGraph{}
21
+ g.addNode("a")
22
+
23
+ if err := g.addEdge("a", "a"); err == nil {
24
+ t.Error("expected error for self-loop cycle a -> a")
25
+ }
26
+}
27
+
28
+func TestImportGraphRemoveNodeCleansEdges(t *testing.T) {
29
+ g := &importGraph{}
30
+ g.addNodes([]string{"a", "b", "c"})
31
+ _ = g.addEdge("a", "b")
32
+ _ = g.addEdge("b", "c")
33
+
34
+ g.removeNode("b")
35
+
36
+ if g.exists("b") {
37
+ t.Error("node 'b' should not exist after removeNode")
38
+ }
39
+ if targets, ok := g.edges["b"]; ok && len(targets) > 0 {
40
+ t.Errorf("outgoing edges from removed node 'b' should be cleared, got %v", targets)
41
+ }
42
+ if g.areConnected("a", "b") {
43
+ t.Error("incoming edge 'a' -> 'b' should be removed when 'b' is removed")
44
+ }
45
+}