fix: C action buffer lengths, byte-faithful callbacks, runtime finalize
Resolves the 8 gaps in docs/rewrite/notes/review-rv10-codex.md (final-Z13.md): - P1 memory safety: the C key-table action (and hovered-link/open-URL payloads) could advertise a length larger than the NUL-truncated allocation. A counted_bytes helper now passes the full bytes plus a trailing NUL with len == byte count, like Zig's backing slices; all C pointer+len structs were audited and tested to read exactly len. - ghostty-bench args follow cli/args.zig (ordered duplicates, empty value resets, first bad value errors, parseBool spellings); the C benchmark tokenizer uses the ArgIteratorGeneral port. - OSC 7 derived titles, desktop notifications and OSC 8 hover links forward raw bytes to the runtime; GTK converts only for display. - C diagnostic getter exports original bytes; escaped surrogates report Utf8CannotEncodeSurrogateHalf; config float formatters print `nan`. - Config::finalize_for(AppRuntime): GTK-only finalization (gtk-single- instance=detect) and termio's cgroup hooks apply only to the GTK runtime, so libghostty keeps `detect` like Zig. Test Plan: - cargo test --workspace --no-fail-fast (exit 0) - cargo test -p ghostty-lib --features test-platform - just check-wasm (macOS/Windows clippy re-run after the concurrent terminal changes land)
This commit is contained in:
1 parent
7b3fffded3
commit
da9599140b
21 files changed
+479
-133
No files matched your search
@@ -4,11 +4,16 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum StringError {
|
||||
InvalidString,
|
||||
/// `std.unicode.utf8Encode` of an escaped surrogate half.
|
||||
Utf8CannotEncodeSurrogateHalf,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for StringError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("InvalidString")
|
||||
f.write_str(match self {
|
||||
StringError::InvalidString => "InvalidString",
|
||||
StringError::Utf8CannotEncodeSurrogateHalf => "Utf8CannotEncodeSurrogateHalf",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +93,11 @@ pub fn parse_bytes(input: impl AsRef<[u8]>) -> Result<Vec<u8>, StringError> {
|
||||
continue;
|
||||
}
|
||||
let cp = parse_escape_sequence(bytes, &mut i).ok_or(StringError::InvalidString)?;
|
||||
let ch = char::from_u32(cp).ok_or(StringError::InvalidString)?;
|
||||
let ch = char::from_u32(cp).ok_or(if (0xd800..=0xdfff).contains(&cp) {
|
||||
StringError::Utf8CannotEncodeSurrogateHalf
|
||||
} else {
|
||||
StringError::InvalidString
|
||||
})?;
|
||||
out.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes());
|
||||
}
|
||||
Ok(out)
|
||||
@@ -200,6 +209,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_invalid() {
|
||||
assert_eq!(
|
||||
parse("\\u{d800}"),
|
||||
Err(StringError::Utf8CannotEncodeSurrogateHalf)
|
||||
);
|
||||
assert_eq!(
|
||||
crate::cli_args::ArgError::from(StringError::Utf8CannotEncodeSurrogateHalf),
|
||||
crate::cli_args::ArgError::other("Utf8CannotEncodeSurrogateHalf")
|
||||
);
|
||||
assert_eq!(parse("\\q"), Err(StringError::InvalidString));
|
||||
assert_eq!(parse("\\"), Err(StringError::InvalidString));
|
||||
assert_eq!(parse("\\u{}"), Err(StringError::InvalidString));
|
||||
|
||||
Reference in new issue
Block a user