Commit e00ae5c
committed
Fix unreachable!() panic when DOCTYPE appears between text runs in element content
The deserializer's `drain_text` merges consecutive `Text`, `CData`, and
`GeneralRef` payload events into a single `DeEvent::Text` so that
`read_text` and friends see at most one text run per element. DOCTYPE
events were not part of that merge: `drain_text`'s break condition
(`current_event_is_last_text`) treats DocType as a non-text event and
exits the loop, and the outer `next()` resumes by capturing the
DocType and continuing — emitting a *second* `DeEvent::Text` for the
trailing text run.
For input like `<a>x<!DOCTYPE y>z</a>` (and shapes derived from it),
`read_text` then matched on a second `DeEvent::Text` and tripped
`unreachable!()` with the comment 'Cannot be two consequent Text
events, they would be merged into one'. The merge invariant was the
right idea — the implementation just missed the DocType case.
Fix: treat DocType as transparent during the text drain. It still goes
through `entity_resolver.capture()` (so DTD entities defined inside
the document body remain available for later `&entity;` resolution),
but the surrounding text runs are merged into one `DeEvent::Text` and
the `unreachable!()` is no longer reachable from valid or malformed
real-world input.
Discovered via libFuzzer running against a SAML deserializer harness
on the consuming application — the input that surfaced it is a
100-byte sequence containing nested DOCTYPE declarations inside what
the parser treats as element content.
Adds four regression tests in a new `doctype_in_element_text` module
in `tests/serde-de.rs`: a minimal repro (`<a>x<!DOCTYPE y>z</a>`), a
multi-DOCTYPE shape mirroring the original fuzzer find, a leading-
DOCTYPE variant, and a whitespace-around-DOCTYPE variant (added per
review feedback) confirming that adjacent whitespace is preserved
verbatim when the surrounding text runs are merged. Full
`cargo test --all-features` stays green (1,712 passing).1 parent 2778564 commit e00ae5c
3 files changed
Lines changed: 113 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
21 | 31 | | |
22 | 32 | | |
23 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2372 | 2372 | | |
2373 | 2373 | | |
2374 | 2374 | | |
2375 | | - | |
| 2375 | + | |
| 2376 | + | |
| 2377 | + | |
| 2378 | + | |
| 2379 | + | |
| 2380 | + | |
| 2381 | + | |
| 2382 | + | |
2376 | 2383 | | |
2377 | 2384 | | |
2378 | | - | |
| 2385 | + | |
| 2386 | + | |
| 2387 | + | |
| 2388 | + | |
2379 | 2389 | | |
2380 | 2390 | | |
2381 | 2391 | | |
2382 | 2392 | | |
2383 | 2393 | | |
2384 | 2394 | | |
2385 | 2395 | | |
| 2396 | + | |
| 2397 | + | |
| 2398 | + | |
| 2399 | + | |
2386 | 2400 | | |
2387 | 2401 | | |
2388 | 2402 | | |
| |||
2399 | 2413 | | |
2400 | 2414 | | |
2401 | 2415 | | |
| 2416 | + | |
| 2417 | + | |
| 2418 | + | |
| 2419 | + | |
| 2420 | + | |
2402 | 2421 | | |
2403 | | - | |
2404 | | - | |
| 2422 | + | |
| 2423 | + | |
| 2424 | + | |
| 2425 | + | |
2405 | 2426 | | |
2406 | 2427 | | |
2407 | 2428 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1896 | 1896 | | |
1897 | 1897 | | |
1898 | 1898 | | |
| 1899 | + | |
| 1900 | + | |
| 1901 | + | |
| 1902 | + | |
| 1903 | + | |
| 1904 | + | |
| 1905 | + | |
| 1906 | + | |
| 1907 | + | |
| 1908 | + | |
| 1909 | + | |
| 1910 | + | |
| 1911 | + | |
| 1912 | + | |
| 1913 | + | |
| 1914 | + | |
| 1915 | + | |
| 1916 | + | |
| 1917 | + | |
| 1918 | + | |
| 1919 | + | |
| 1920 | + | |
| 1921 | + | |
| 1922 | + | |
| 1923 | + | |
| 1924 | + | |
| 1925 | + | |
| 1926 | + | |
| 1927 | + | |
| 1928 | + | |
| 1929 | + | |
| 1930 | + | |
| 1931 | + | |
| 1932 | + | |
| 1933 | + | |
| 1934 | + | |
| 1935 | + | |
| 1936 | + | |
| 1937 | + | |
| 1938 | + | |
| 1939 | + | |
| 1940 | + | |
| 1941 | + | |
| 1942 | + | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
| 1946 | + | |
| 1947 | + | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
| 1953 | + | |
| 1954 | + | |
| 1955 | + | |
| 1956 | + | |
| 1957 | + | |
| 1958 | + | |
| 1959 | + | |
| 1960 | + | |
| 1961 | + | |
| 1962 | + | |
| 1963 | + | |
| 1964 | + | |
| 1965 | + | |
| 1966 | + | |
| 1967 | + | |
| 1968 | + | |
| 1969 | + | |
| 1970 | + | |
| 1971 | + | |
| 1972 | + | |
| 1973 | + | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
1899 | 1977 | | |
1900 | 1978 | | |
1901 | 1979 | | |
| |||
0 commit comments