|
1 | 1 | package containers_test |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "encoding/xml" |
4 | 5 | "os" |
5 | 6 | "path/filepath" |
6 | 7 |
|
@@ -334,6 +335,38 @@ var _ = Describe("Tomcat Container", func() { |
334 | 335 | Expect(string(content)).To(ContainSubstring(`docBase="${user.home}/app/myapp.war"`)) |
335 | 336 | }) |
336 | 337 |
|
| 338 | + It("XML-escapes WAR filenames containing XML-sensitive characters", func() { |
| 339 | + // A WAR filename may legally contain &, <, > which are XML-sensitive. |
| 340 | + // Interpolated raw into the docBase attribute they produce an invalid |
| 341 | + // descriptor that Tomcat fails to parse. The filename must be escaped. |
| 342 | + warName := "my&a<b>c.war" |
| 343 | + Expect(os.WriteFile(filepath.Join(buildDir, warName), []byte("fakewar"), 0644)).To(Succeed()) |
| 344 | + |
| 345 | + err := container.Finalize() |
| 346 | + Expect(err).NotTo(HaveOccurred()) |
| 347 | + |
| 348 | + tomcatDir := filepath.Join(depsDir, "0", "tomcat") |
| 349 | + contextFile := filepath.Join(tomcatDir, "conf", "Catalina", "localhost", "ROOT.xml") |
| 350 | + Expect(contextFile).To(BeAnExistingFile()) |
| 351 | + content, _ := os.ReadFile(contextFile) |
| 352 | + contentStr := string(content) |
| 353 | + |
| 354 | + // Raw sensitive characters must not leak into the descriptor. |
| 355 | + Expect(contentStr).NotTo(ContainSubstring("my&a<b>c.war"), |
| 356 | + "raw unescaped WAR filename produced invalid XML:\n%s", contentStr) |
| 357 | + // Escaped form present. |
| 358 | + Expect(contentStr).To(ContainSubstring("my&a<b>c.war"), |
| 359 | + "expected XML-escaped WAR filename in docBase:\n%s", contentStr) |
| 360 | + |
| 361 | + // The descriptor must be well-formed XML. |
| 362 | + var parsed struct { |
| 363 | + DocBase string `xml:"docBase,attr"` |
| 364 | + } |
| 365 | + Expect(xml.Unmarshal(content, &parsed)).To(Succeed(), |
| 366 | + "generated descriptor is not well-formed XML:\n%s", contentStr) |
| 367 | + Expect(parsed.DocBase).To(Equal("${user.home}/app/my&a<b>c.war")) |
| 368 | + }) |
| 369 | + |
337 | 370 | It("removes ROOT.xml when packaged WAR uses non-root context_path", func() { |
338 | 371 | Expect(os.WriteFile(filepath.Join(buildDir, "myapp.war"), []byte("fakewar"), 0644)).To(Succeed()) |
339 | 372 | os.Setenv("JBP_CONFIG_TOMCAT", `{tomcat: {context_path: /my/path}}`) |
|
0 commit comments