How to correctly resize a sentinel-terminated array?

Welcome to the forum!
I agree that it’s weird that there is no realloc for sentinel-terminated slices.

Am I correct to assume that stringProvider is the C API function and you have no control over that?
(if you have control over it I would just use an ArrayList instead, which has more safety)

For now I can only suggest you some less gross versions:

test "method 2 advanced: sentinel slicing" {
    const buffer = try alloc.alloc(u8, 9000);

    const length = stringProvider(@ptrCast(buffer.ptr));
    // less gross: no pointer cast and no length adjusting.
    var minimal: [:0]u8 = (try alloc.realloc(buffer, length + 1))[0..length :0];

    try std.testing.expectEqualSentinel(u8, 0, target, minimal);

test "method 3 advanced: duplicate with less allocations" {
    var buffer: [9000]u8 = undefined;

    const length = stringProvider(@ptrCast(&buffer));
    // less gross: Still always requires an extra memcpy, but we removed the first alloc by using the stack.
    const minimal = try alloc.dupeZ(u8, buffer[0..length]);

    try std.testing.expectEqualSentinel(u8, 0, target, minimal);