Skip to content

Commit c40cedd

Browse files
committed
test: quarantine known upstream URI decoding failures
Exclude only the two saved reader seeds from normal replay and ignore their Jazzer deduplication tokens during reader fuzzing. Keep the source inputs, limit the quarantine to the affected engine version, and provide fuzzIncludeKnownFailures to reproduce both failures explicitly.
1 parent 1efe5d8 commit c40cedd

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

‎docs/site/index.html‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ <h3 id="fuzzing">Coverage-guided fuzzing</h3>
561561
<p>Each target accepts at most 4096 input bytes and has a 10-second per-input timeout. The reader additionally limits depth to 20 and alias expansion weight to 64. Each fuzz task defaults to five minutes and a 1 GiB JVM heap. The daily workflow searches both targets and retains the generated corpus between runs; manual runs can select 30 seconds, five minutes or ten minutes per target. Test and coverage reports, findings and the corpus are uploaded even when a search fails.</p>
562562
<p>Checked-in seeds live under <code>fuzzing/src/test/resources/com/charleskorn/kaml/fuzz</code>. Reader seeds contain UTF-8 YAML. Writer seeds start with an options byte, followed by UTF-8 text: bits 0–1 select the single-line style, bits 2–4 select the multiline style modulo five, bit 5 selects flow sequences and bit 6 disables default encoding. Their bytes are preserved by <code>.gitattributes</code>. Invalid UTF-8 is replaced before testing, so these targets test YAML and string handling rather than UTF-8 validation.</p>
563563
<p>New coverage inputs go to <code>fuzzing/.cifuzz-corpus</code>; failing inputs are saved beside the checked-in seeds. Coverage reports and Java reproducers go to <code>fuzzing/build/fuzz</code>. Re-run <code>./gradlew :fuzzing:test</code> to reproduce a saved failure without further fuzzing. Reduce each finding to a small regression in <code>commonTest</code>, verify it on JVM, JS, Wasm and Native, and retain the original input as a corpus seed. A finite search without findings does not establish correctness for all inputs.</p>
564+
<p>Two known upstream URI-decoding failures are temporarily quarantined: their saved seeds are excluded from normal replay, and the reader search ignores only their Jazzer stack fingerprints. The source seeds remain in the repository. The quarantine automatically ends when the configured SnakeYAML Engine version changes. Use <code>-PfuzzIncludeKnownFailures=true</code> with either <code>:fuzzing:test</code> or <code>:fuzzing:fuzzReader</code> to include them now. Other failures remain enabled.</p>
564565
<h3 id="references">References</h3>
565566
<ul>
566567
<li><a href="http://yaml.org/spec/1.2/spec.html">YAML 1.2 Specification</a></li>

‎fuzzing/build.gradle.kts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ dependencies {
4848
testRuntimeOnly(libs.junit.platform.launcher)
4949
}
5050

51+
// Temporary quarantine for the two URI double-decoding failures in Engine 5.0.0.
52+
// Keep the source seeds; changing the engine version automatically re-enables them.
53+
val quarantineKnownReaderFailures =
54+
libs.versions.snakeyaml.engine.kmp
55+
.get() == "5.0.0" &&
56+
!providers.gradleProperty("fuzzIncludeKnownFailures").map(String::toBooleanStrict).getOrElse(false)
57+
val knownReaderFailures =
58+
mapOf(
59+
"crash-7895f33f6e9e327248d69d3bf4a934dfe0dcc0e3" to "71896d4ac12e007f",
60+
"crash-487d9a846211b97053cc6df99deb2df8e394cad4" to "c3518e77b28b31d7",
61+
)
62+
63+
tasks.processTestResources {
64+
if (quarantineKnownReaderFailures) {
65+
knownReaderFailures.keys.forEach { seed ->
66+
exclude("com/charleskorn/kaml/fuzz/YamlReaderFuzzTestInputs/read/$seed")
67+
}
68+
}
69+
}
70+
5171
tasks.withType<Test>().configureEach {
5272
useJUnitPlatform()
5373
maxHeapSize = "1g"
@@ -68,6 +88,9 @@ tasks.test {
6888
environment("JAZZER_FUZZ", "")
6989
environment("JAZZER_COVERAGE", "")
7090
forkEvery = 1
91+
if (quarantineKnownReaderFailures) {
92+
doFirst { logger.lifecycle("Quarantining two known SnakeYAML URI seeds; use -PfuzzIncludeKnownFailures=true to replay them.") }
93+
}
7194
}
7295

7396
for (target in listOf("Reader", "Writer")) {
@@ -85,6 +108,11 @@ for (target in listOf("Reader", "Writer")) {
85108
// otherwise time the entire campaign as one invocation of the fuzz method.
86109
systemProperty("junit.jupiter.execution.timeout.mode", "disabled")
87110
systemProperty("jazzer.max_duration", providers.gradleProperty("fuzzDuration").getOrElse("5m"))
111+
if (target == "Reader" && quarantineKnownReaderFailures) {
112+
// Ignore only these known stack fingerprints, not whole exception classes or tags.
113+
systemProperty("jazzer.ignore", knownReaderFailures.values.joinToString(","))
114+
doFirst { logger.lifecycle("Ignoring two known SnakeYAML URI fingerprints; use -PfuzzIncludeKnownFailures=true to include them.") }
115+
}
88116
val report =
89117
layout.buildDirectory
90118
.dir("fuzz/$target")

0 commit comments

Comments
 (0)