╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │1128 - try transport.writePacket(io, allocator, writer, &[_]u8{SSH_MSG_NEWKEYS});│ │1115 + try transport.writePacket(io, writer, &[_]u8{SSH_MSG_NEWKEYS}); │ │1116 │ │1117 const peer_newkeys = try transport.readPacket(allocator, reader, strict); │ │1118 defer allocator.free(peer_newkeys); │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │1286 pub fn writePacket( │ │1287 self: *Cipher, │ │1288 io: std.Io, │ │1302 - allocator: std.mem.Allocator,│ │1289 writer: *std.Io.Writer, │ │1290 payload: []const u8, │ │1291 ) !void { │ ╰───────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │1296 │ │1297 const nonce = makeNonce(self.seq); │ │1298 │ │1313 - // plaintext body = padding_length || payload || random padding │ │1314 - const body = try allocator.alloc(u8, body_len); │ │1315 - defer allocator.free(body); │ │1299 + // plaintext body = padding_length || payload || random padding.│ │1300 + // stack-allocated to avoid a heap alloc on every packet. │ │1301 + var body_buf: [max_packet_len]u8 = undefined; │ │1302 + if (body_len > body_buf.len) return error.PacketTooLarge; │ │1303 + const body = body_buf[0..body_len]; │ │1304 body[0] = padding_len; │ │1305 @memcpy(body[1 .. 1 + payload.len], payload); │ │1306 io.random(body[1 + payload.len ..]); │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │1428 defer accept.deinit(allocator); │ │1429 try accept.append(allocator, SSH_MSG_SERVICE_ACCEPT); │ │1430 try writeStringField(&accept, allocator, "ssh-userauth"); │ │1443 - try sc_cipher.writePacket(io, allocator, writer, accept.items); │ │1431 + try sc_cipher.writePacket(io, writer, accept.items); │ │1432 } │ │1433 │ │1434 // step 2: USERAUTH loop until SUCCESS. accept any ed25519 key whose│ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │1486 try pk_ok.append(allocator, SSH_MSG_USERAUTH_PK_OK); │ │1487 try writeStringField(&pk_ok, allocator, algo); │ │1488 try writeStringField(&pk_ok, allocator, pubkey_blob); │ │1501 - try sc_cipher.writePacket(io, allocator, writer, pk_ok.items);│ │1489 + try sc_cipher.writePacket(io, writer, pk_ok.items); │ │1490 continue; │ │1491 } │ │1492 │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │1511 continue; │ │1512 } │ │1513 │ │1526 - try sc_cipher.writePacket(io, allocator, writer, &[_]u8{SSH_MSG_USERAUTH_SUCCESS});│ │1514 + try sc_cipher.writePacket(io, writer, &[_]u8{SSH_MSG_USERAUTH_SUCCESS}); │ │1515 return formatFingerprint(pubkey_blob); │ │1516 } │ │1517 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │1527 try buf.append(allocator, SSH_MSG_USERAUTH_FAILURE); │ │1528 try writeNameList(&buf, allocator, &.{"publickey"}); // allowed methods │ │1529 try buf.append(allocator, 0); // partial_success = false │ │1542 - try sc_cipher.writePacket(io, allocator, writer, buf.items); │ │1530 + try sc_cipher.writePacket(io, writer, buf.items); │ │1531 } │ │1532 │ │1533 /// Append the canonical publickey-signed-data bytes (RFC 4252 §7) to `buf`.│ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │1725 defer allocator.free(name); │ │1726 const want_reply = (try r.takeByte()) != 0; │ │1727 if (want_reply) { │ │1740 - try sc_cipher.writePacket(io, allocator, writer, &[_]u8{SSH_MSG_REQUEST_FAILURE});│ │1728 + try sc_cipher.writePacket(io, writer, &[_]u8{SSH_MSG_REQUEST_FAILURE}); │ │1729 } │ │1730 } │ │1731 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │1770 try writeU32(&reply, allocator, local_id); │ │1771 try writeU32(&reply, allocator, initial_recv_window); │ │1772 try writeU32(&reply, allocator, max_packet_size); │ │1785 - try sc_cipher.writePacket(io, allocator, writer, reply.items);│ │1773 + try sc_cipher.writePacket(io, writer, reply.items); │ │1774 │ │1775 return .{ │ │1776 .local_id = local_id, │ ╰────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │1804 try writeU32(&reply, allocator, reason); │ │1805 try writeStringField(&reply, allocator, description); │ │1806 try writeStringField(&reply, allocator, ""); // language tag │ │1819 - try sc_cipher.writePacket(io, allocator, writer, reply.items);│ │1807 + try sc_cipher.writePacket(io, writer, reply.items); │ │1808 } │ │1809 │ │1810 const RequestKind = enum { shell, exec }; │ ╰────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯