libvt: return safe pointers for empty output

Normalize empty buffers and borrowed strings at the libghostty-vt C
boundary to null pointers.

Zig can use sentinel addresses such as 0x1 for empty slices. Returning
these pointers to Go can cause a fatal invalid-pointer error when the
runtime relocates a goroutine's stack, even though the length is zero.
This commit is contained in:
Mitchell Hashimoto
2026-09-07 20:41:55 -07:00
parent da9e21602f
commit dd2edd760d
11 changed files with 140 additions and 32 deletions

View File

@@ -224,7 +224,8 @@ typedef struct GhosttyAllocator {
*
* @param allocator Pointer to the allocator to use, or NULL for the default
* @param len Number of bytes to allocate
* @return Pointer to the allocated buffer, or NULL if allocation failed
* @return Pointer to the allocated buffer, or NULL if len is zero or
* allocation failed
*
* @ingroup allocator
*/

View File

@@ -196,6 +196,8 @@ GHOSTTY_API GhosttyResult ghostty_formatter_format_buf(GhosttyFormatter formatte
* The caller is responsible for freeing the returned buffer with
* ghostty_free(), passing the same allocator (or NULL for the default)
* that was used for the allocation.
* Empty output returns GHOSTTY_SUCCESS with *out_ptr set to NULL and
* *out_len set to zero. This result can be passed to ghostty_free().
*
* @param formatter The formatter handle (must not be NULL)
* @param allocator Pointer to allocator, or NULL to use the default allocator

View File

@@ -907,6 +907,8 @@ GHOSTTY_API GhosttyResult ghostty_terminal_selection_format_buf(
* The returned buffer is allocated using allocator, or the default allocator
* if NULL is passed. The caller owns the returned buffer and must free it with
* ghostty_free(), passing the same allocator and returned length.
* Empty output returns GHOSTTY_SUCCESS with *out_ptr set to NULL and
* *out_len set to zero. This result can be passed to ghostty_free().
*
* The returned bytes are not NUL-terminated. This supports plain text, VT, and
* HTML uniformly as byte output.

View File

@@ -2176,7 +2176,8 @@ GHOSTTY_API GhosttyResult ghostty_terminal_continuation_buf(
* The returned bytes are allocated with allocator, or the default allocator
* when allocator is NULL. The caller must release them with ghostty_free(),
* passing the same allocator and returned length. An empty continuation is a
* successful zero-length allocation.
* successful result with *out_ptr set to NULL and *out_len set to zero,
* which can also be passed to ghostty_free().
* Continuation tracking must have been enabled by setting
* GHOSTTY_TERMINAL_OPT_CONTINUATION_MAX_BYTES to a nonzero value before the
* input that produced the continuation was written.

View File

@@ -262,6 +262,8 @@ typedef enum GHOSTTY_ENUM_TYPED {
*
* The memory is not owned by this struct. The pointer is only valid
* for the lifetime documented by the API that produces or consumes it.
* Empty strings produced by the library have a non-NULL pointer to valid
* storage.
*/
typedef struct {
/** Pointer to the string bytes. */