|
3 | 3 | //! Format reference: <https://github.com/rockdaboot/libpsl/blob/master/src/psl-make-dafsa> |
4 | 4 | //! (writer) and <https://github.com/rockdaboot/libpsl/blob/master/src/lookup_string_in_fixed_set.c> |
5 | 5 | //! (reader). The on-disk file is a 16-byte ASCII header (`.DAFSA@PSL_<ver>` padded |
6 | | -//! to 16 bytes with spaces and terminated by LF) followed by a byte-coded DAFSA. |
7 | | -//! Only version 0 exists today. |
| 6 | +//! to 16 bytes with spaces and terminated by LF) followed by a byte-coded DAFSA, |
| 7 | +//! optionally with a trailing `0x01` byte in UTF-8 mode. Only version 0 exists today. |
| 8 | +//! |
| 9 | +//! Deviations from libpsl `psl_is_public_suffix`: |
| 10 | +//! |
| 11 | +//! * No prevailing `*` rule for unknown single-label TLDs. libpsl treats any |
| 12 | +//! single-label host as a public suffix; this reader returns `None`, so |
| 13 | +//! `localhost` can be used as a relying-party id against itself. |
| 14 | +//! * Multibyte (UTF-8) keys are not supported. WebAuthn rp.ids and origin |
| 15 | +//! hosts are always IDN-ASCII (punycode) by the time they reach the PSL, |
| 16 | +//! and the DAFSA stores IDN rules in punycode form regardless of its |
| 17 | +//! internal encoding mode, so ASCII queries match correctly. |
8 | 18 |
|
9 | 19 | use std::path::{Path, PathBuf}; |
10 | 20 |
|
@@ -180,6 +190,7 @@ fn lookup(graph: &[u8], key: &[u8]) -> Option<u8> { |
180 | 190 | } |
181 | 191 | offset += 1; |
182 | 192 | key_pos += 1; |
| 193 | + // Dive into the child node. |
183 | 194 | pos = offset; |
184 | 195 | } |
185 | 196 | None |
@@ -328,14 +339,15 @@ mod tests { |
328 | 339 | #[test] |
329 | 340 | fn public_suffix_exception_overrides_wildcard() { |
330 | 341 | let psl = loaded(); |
331 | | - // foo.kw has the exception flag, so it is NOT a public suffix even |
332 | | - // though *.kw would otherwise make it one. The longest suffix that |
333 | | - // applies is `kw` itself (which is a suffix because *.kw implicitly |
334 | | - // makes the parent a public suffix per the libpsl/PSL algorithm). |
| 342 | + // foo.kw has the EXCEPTION flag so direct lookup returns "not a |
| 343 | + // suffix"; the search then strips a label to "kw", which is in the |
| 344 | + // DAFSA with the WILDCARD flag (no EXCEPTION), so kw itself is the |
| 345 | + // public suffix. |
335 | 346 | assert_eq!(psl.public_suffix("foo.kw").as_deref(), Some("kw")); |
336 | | - // The exception rule matches sub.foo.kw too (its rightmost two |
337 | | - // labels are foo.kw), so the prevailing rule is the exception with |
338 | | - // its leftmost label stripped, giving "kw". |
| 347 | + // For sub.foo.kw: exact lookup misses; parent foo.kw is found but |
| 348 | + // has no WILDCARD bit, so the wildcard-fallback rejects it; the |
| 349 | + // search then strips down to foo.kw (still excepted) and finally to |
| 350 | + // kw (wildcard, suffix). |
339 | 351 | assert_eq!(psl.public_suffix("sub.foo.kw").as_deref(), Some("kw")); |
340 | 352 | } |
341 | 353 |
|
|
0 commit comments