From: Stefan Sperling Subject: Re: got fails to build on alpha To: Theo Buehler Cc: Martijn van Duren , "gameoftrees@openbsd.org" Date: Sat, 10 Oct 2026 14:15:29 +0200 On Fri, Oct 09, 2026 at 04:41:19PM +0200, Theo Buehler wrote: > On Fri, Oct 09, 2026 at 04:39:03PM +0200, Stefan Sperling wrote: > > This looks like something Miod might be qualified to take a look at? > > These files both have pretty huge structures on the stack. Might this be > releated? In that case, the following diff might help: move buffers of size GOT_PKT_MAX off the stack M lib/serve.c | 130+ 45- M libexec/got-fetch-pack/got-fetch-pack.c | 19+ 12- M libexec/got-send-pack/got-send-pack.c | 12+ 6- 3 files changed, 161 insertions(+), 63 deletions(-) commit - 10f51ecc4cbfab15f63d68920c9674a2995fd394 commit + 22805600d8994acd612c568d0013c48a4476e16d blob - d87245ee471ce963a0c8b81e4d9fc75c03a378d8 blob + 219c75af8f0167f9d23332b05bfc92d93cfcd7bf --- lib/serve.c +++ lib/serve.c @@ -120,36 +120,48 @@ send_ref(int outfd, uint8_t *id, const char *refname, { const struct got_error *err = NULL; char hex[GOT_HASH_DIGEST_STRING_MAXLEN]; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; size_t len, capalen = 0; if (got_hash_digest_to_str(id, hex, sizeof(hex), algo) == NULL) return got_error(GOT_ERR_BAD_OBJ_ID); - len = snprintf(buf, sizeof(buf), "%s %s", hex, refname); - if (len >= sizeof(buf)) - return got_error(GOT_ERR_NO_SPACE); + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); + len = snprintf(buf, bufsize, "%s %s", hex, refname); + if (len >= bufsize) { + err = got_error(GOT_ERR_NO_SPACE); + goto done; + } + if (send_capabilities) { if (client_is_reading) { err = append_read_capabilities(&capalen, len, - symrefstr, buf, sizeof(buf), algo); + symrefstr, buf, bufsize, algo); } else { err = append_write_capabilities(&capalen, len, - symrefstr, buf, sizeof(buf), algo); + symrefstr, buf, bufsize, algo); } if (err) - return err; + goto done; len += capalen; } - if (len + 1 >= sizeof(buf)) - return got_error(GOT_ERR_NO_SPACE); + if (len + 1 >= bufsize) { + err = got_error(GOT_ERR_NO_SPACE); + goto done; + } buf[len] = '\n'; len++; buf[len] = '\0'; - return got_pkt_writepkt(outfd, buf, len, chattygot); + err = got_pkt_writepkt(outfd, buf, len, chattygot); +done: + free(buf); + return err; } static const struct got_error * @@ -157,7 +169,8 @@ send_zero_refs(int outfd, int client_is_reading, int c { const struct got_error *err = NULL; const char *line; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; size_t len, capalen = 0; if (algo == GOT_HASH_SHA1) @@ -167,23 +180,32 @@ send_zero_refs(int outfd, int client_is_reading, int c else return got_error(GOT_ERR_OBJECT_FORMAT); - len = strlcpy(buf, line, sizeof(buf)); - if (len >= sizeof(buf)) - return got_error(GOT_ERR_NO_SPACE); + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); + len = strlcpy(buf, line, bufsize); + if (len >= bufsize) { + err = got_error(GOT_ERR_NO_SPACE); + goto done; + } + if (client_is_reading) { err = append_read_capabilities(&capalen, len, - NULL, buf, sizeof(buf), algo); + NULL, buf, bufsize, algo); if (err) - return err; + goto done; } else { err = append_write_capabilities(&capalen, len, - NULL, buf, sizeof(buf), algo); + NULL, buf, bufsize, algo); if (err) - return err; + goto done; } - return got_pkt_writepkt(outfd, buf, len + capalen, chattygot); + err = got_pkt_writepkt(outfd, buf, len + capalen, chattygot); +done: + free(buf); + return err; } static void @@ -719,18 +741,29 @@ done: static const struct got_error * send_ack(int outfd, uint8_t *id, int chattygot, int algo) { + const struct got_error *err = NULL; char hex[GOT_HASH_DIGEST_STRING_MAXLEN]; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; int len; if (got_hash_digest_to_str(id, hex, sizeof(hex), algo) == NULL) return got_error(GOT_ERR_BAD_OBJ_ID); - len = snprintf(buf, sizeof(buf), "ACK %s\n", hex); - if (len >= sizeof(buf)) - return got_error(GOT_ERR_NO_SPACE); + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); - return got_pkt_writepkt(outfd, buf, len, chattygot); + len = snprintf(buf, bufsize, "ACK %s\n", hex); + if (len >= bufsize) { + err = got_error(GOT_ERR_NO_SPACE); + goto done; + } + + err = got_pkt_writepkt(outfd, buf, len, chattygot); +done: + free(buf); + return err; } static const struct got_error * @@ -868,7 +901,8 @@ relay_progress_reports(struct imsgbuf *ibuf, int outfd const struct got_error *err = NULL; int pack_starting = 0; struct gotd_imsg_packfile_progress iprog; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; struct imsg imsg; size_t datalen; int p_deltify = 0, n; @@ -876,6 +910,10 @@ relay_progress_reports(struct imsgbuf *ibuf, int outfd memset(&imsg, 0, sizeof(imsg)); + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); + while (!pack_starting && err == NULL) { err = gotd_imsg_poll_recv(&imsg, ibuf, 0); if (err) @@ -901,14 +939,14 @@ relay_progress_reports(struct imsgbuf *ibuf, int outfd iprog.nobj_total; } buf[0] = GOT_SIDEBAND_PROGRESS_INFO; - n = snprintf(&buf[1], sizeof(buf) - 1, + n = snprintf(&buf[1], bufsize - 1, "%d commits colored, " "%d objects found, " "deltify %d%%%s", iprog.ncolored, iprog.nfound, p_deltify, eol); - if (n >= sizeof(buf) - 1) + if (n >= bufsize - 1) break; err = got_pkt_writepkt(outfd, buf, 1 + n, chattygot); break; @@ -920,6 +958,7 @@ relay_progress_reports(struct imsgbuf *ibuf, int outfd imsg_free(&imsg); } + free(buf); return err; } @@ -928,7 +967,8 @@ serve_read(int infd, int outfd, int gotd_sock, const c int chattygot) { const struct got_error *err = NULL; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; struct imsgbuf ibuf; enum protostate { STATE_EXPECT_WANT, @@ -945,6 +985,12 @@ serve_read(int infd, int outfd, int gotd_sock, const c return got_error_from_errno("imsgbuf_init"); imsgbuf_allow_fdpass(&ibuf); + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } + err = announce_refs(outfd, &algo, &ibuf, 1, repo_path, chattygot); if (err) goto done; @@ -952,7 +998,7 @@ serve_read(int infd, int outfd, int gotd_sock, const c while (curstate != STATE_DONE) { int n; - err = got_pkt_readpkt(&n, infd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, infd, buf, bufsize, chattygot, timeout); if (err) goto done; @@ -972,7 +1018,7 @@ serve_read(int infd, int outfd, int gotd_sock, const c * anything we should receive a flush * packet followed by EOF. */ - r = read(infd, buf, sizeof(buf)); + r = read(infd, buf, bufsize); if (r == -1) { err = got_error_from_errno("read"); goto done; @@ -1056,7 +1102,7 @@ serve_read(int infd, int outfd, int gotd_sock, const c goto done; pack_chunksize = GOT_SIDEBAND_64K_PACKFILE_DATA_MAX; } else - pack_chunksize = sizeof(buf); + pack_chunksize = bufsize; for (;;) { ssize_t r; @@ -1087,6 +1133,7 @@ serve_read(int infd, int outfd, int gotd_sock, const c } done: imsgbuf_clear(&ibuf); + free(buf); if (packfd != -1 && close(packfd) == -1 && err == NULL) err = got_error_from_errno("close"); if (err) @@ -1245,7 +1292,8 @@ recv_packfile(struct imsg *imsg, struct imsgbuf *ibuf, const struct got_error *err = NULL; size_t datalen; int packfd; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; int pack_done = 0; datalen = imsg->hdr.len - IMSG_HEADER_SIZE; @@ -1264,6 +1312,10 @@ recv_packfile(struct imsg *imsg, struct imsgbuf *ibuf, if (err) return err; + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); + while (!pack_done) { ssize_t r = 0; @@ -1273,7 +1325,7 @@ recv_packfile(struct imsg *imsg, struct imsgbuf *ibuf, break; err = NULL; } else { - r = read(infd, buf, sizeof(buf)); + r = read(infd, buf, bufsize); if (r == -1) { err = got_error_from_errno("read"); break; @@ -1312,6 +1364,7 @@ recv_packfile(struct imsg *imsg, struct imsgbuf *ibuf, } close(packfd); + free(buf); return err; } @@ -1320,7 +1373,8 @@ report_unpack_status(struct imsg *imsg, int outfd, int { const struct got_error *err = NULL; struct gotd_imsg_packfile_status istatus; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; size_t datalen, len; char *reason = NULL; @@ -1337,11 +1391,17 @@ report_unpack_status(struct imsg *imsg, int outfd, int goto done; } + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } + if (err == NULL) - len = snprintf(buf, sizeof(buf), "unpack ok\n"); + len = snprintf(buf, bufsize, "unpack ok\n"); else - len = snprintf(buf, sizeof(buf), "unpack %s\n", reason); - if (len >= sizeof(buf)) { + len = snprintf(buf, bufsize, "unpack %s\n", reason); + if (len >= bufsize) { err = got_error(GOT_ERR_NO_SPACE); goto done; } @@ -1349,6 +1409,7 @@ report_unpack_status(struct imsg *imsg, int outfd, int err = got_pkt_writepkt(outfd, buf, len, chattygot); done: free(reason); + free(buf); return err; } @@ -1358,7 +1419,8 @@ recv_ref_update_ok(struct imsg *imsg, int outfd, int c const struct got_error *err = NULL; struct gotd_imsg_ref_update_ok iok; size_t datalen, len; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; char *refname = NULL; datalen = imsg->hdr.len - IMSG_HEADER_SIZE; @@ -1377,8 +1439,14 @@ recv_ref_update_ok(struct imsg *imsg, int outfd, int c if (refname == NULL) return got_error_from_errno("strndup"); - len = snprintf(buf, sizeof(buf), "ok %s\n", refname); - if (len >= sizeof(buf)) { + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } + + len = snprintf(buf, bufsize, "ok %s\n", refname); + if (len >= bufsize) { err = got_error(GOT_ERR_NO_SPACE); goto done; } @@ -1386,6 +1454,7 @@ recv_ref_update_ok(struct imsg *imsg, int outfd, int c err = got_pkt_writepkt(outfd, buf, len, chattygot); done: free(refname); + free(buf); return err; } @@ -1395,7 +1464,8 @@ recv_ref_update_ng(struct imsg *imsg, int outfd, int c const struct got_error *err = NULL; struct gotd_imsg_ref_update_ng ing; size_t datalen, len; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; char *refname = NULL, *reason = NULL; datalen = imsg->hdr.len - IMSG_HEADER_SIZE; @@ -1421,8 +1491,14 @@ recv_ref_update_ng(struct imsg *imsg, int outfd, int c goto done; } - len = snprintf(buf, sizeof(buf), "ng %s %s\n", refname, reason); - if (len >= sizeof(buf)) { + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } + + len = snprintf(buf, bufsize, "ng %s %s\n", refname, reason); + if (len >= bufsize) { err = got_error(GOT_ERR_NO_SPACE); goto done; } @@ -1431,6 +1507,7 @@ recv_ref_update_ng(struct imsg *imsg, int outfd, int c done: free(refname); free(reason); + free(buf); return err; } @@ -1439,7 +1516,8 @@ serve_write(int infd, int outfd, int gotd_sock, const int chattygot) { const struct got_error *err = NULL; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; struct imsgbuf ibuf; enum protostate { STATE_EXPECT_REF_UPDATE, @@ -1466,10 +1544,16 @@ serve_write(int infd, int outfd, int gotd_sock, const digest_string_length = got_hash_digest_string_length(algo) - 1; + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } + while (curstate != STATE_EXPECT_PACKFILE) { int n; - err = got_pkt_readpkt(&n, infd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, infd, buf, bufsize, chattygot, timeout); if (err) goto done; @@ -1578,6 +1662,7 @@ serve_write(int infd, int outfd, int gotd_sock, const } done: imsgbuf_clear(&ibuf); + free(buf); if (err) echo_error(err, outfd, chattygot); return err; blob - 20247f76f92f51c1759606ed18bdaacf4b778b5d blob + 6deeaf239393baa41b21a264b91e12cd2aeaa629 --- libexec/got-fetch-pack/got-fetch-pack.c +++ libexec/got-fetch-pack/got-fetch-pack.c @@ -353,7 +353,8 @@ fetch_pack(int fd, int packfd, int expected_algo, int no_head, struct imsgbuf *ibuf) { const struct got_error *err = NULL; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; char hashstr[GOT_HASH_DIGEST_STRING_MAXLEN]; struct got_object_id *have, *want; int is_firstpkt = 1, nref = 0, refsz = 16; @@ -388,8 +389,14 @@ fetch_pack(int fd, int packfd, int expected_algo, err = got_error_from_errno("malloc"); goto done; } + + buf = calloc(1, bufsize); + if (buf == NULL) { + err = got_error_from_errno("calloc"); + goto done; + } while (1) { - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; @@ -652,10 +659,10 @@ fetch_pack(int fd, int packfd, int expected_algo, if (got_object_id_cmp(&have[i], &want[i]) == 0) continue; got_object_id_hex(&want[i], hashstr, sizeof(hashstr)); - n = snprintf(buf, sizeof(buf), "want %s%s\n", hashstr, + n = snprintf(buf, bufsize, "want %s%s\n", hashstr, sent_my_capabilites || my_capabilities == NULL ? "" : my_capabilities); - if (n < 0 || (size_t)n >= sizeof(buf)) { + if (n < 0 || (size_t)n >= bufsize) { err = got_error(GOT_ERR_NO_SPACE); goto done; } @@ -675,8 +682,8 @@ fetch_pack(int fd, int packfd, int expected_algo, RB_FOREACH(pe, got_pathlist_head, have_refs) { struct got_object_id *id = pe->data; got_object_id_hex(id, hashstr, sizeof(hashstr)); - n = snprintf(buf, sizeof(buf), "have %s\n", hashstr); - if (n < 0 || (size_t)n >= sizeof(buf)) { + n = snprintf(buf, bufsize, "have %s\n", hashstr); + if (n < 0 || (size_t)n >= bufsize) { err = got_error(GOT_ERR_NO_SPACE); goto done; } @@ -686,7 +693,7 @@ fetch_pack(int fd, int packfd, int expected_algo, nhave++; } - n = strlcpy(buf, "done\n", sizeof(buf)); + n = strlcpy(buf, "done\n", bufsize); err = got_pkt_writepkt(fd, buf, n, chattygot); if (err) goto done; @@ -695,7 +702,7 @@ fetch_pack(int fd, int packfd, int expected_algo, struct got_object_id common_id; /* The server should ACK the object IDs we need. */ - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; @@ -725,7 +732,7 @@ fetch_pack(int fd, int packfd, int expected_algo, } if (nhave == 0) { - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; @@ -765,7 +772,7 @@ fetch_pack(int fd, int packfd, int expected_algo, "short packet"); goto done; } - if (datalen > sizeof(buf) - 5) { + if (datalen > bufsize - 5) { err = got_error_msg(GOT_ERR_BAD_PACKET, "bad packet length"); goto done; @@ -837,7 +844,7 @@ fetch_pack(int fd, int packfd, int expected_algo, /* No sideband channel. Every byte is packfile data. */ size_t n = 0; err = got_poll_read_full_timeout(fd, &n, - buf, sizeof buf, 1, INFTIM); + buf, bufsize, 1, INFTIM); if (err) { if (err->code != GOT_ERR_EOF) goto done; @@ -944,10 +951,10 @@ done: free(server_capabilities); free(my_capabilities); free(capa); + free(buf); return err; } - int main(int argc, char **argv) { blob - 9b55995e8bfe3159fd77915039d230d0c67df493 blob + e15fe4f0b9c0f13627f4a132eaa7a9841f0d3f06 --- libexec/got-send-pack/got-send-pack.c +++ libexec/got-send-pack/got-send-pack.c @@ -345,7 +345,8 @@ send_pack(int fd, enum got_hash_algorithm algo, struct struct got_pathlist_head *delete_refs, struct imsgbuf *ibuf) { const struct got_error *err = NULL; - char buf[GOT_PKT_MAX]; + char *buf = NULL; + const size_t bufsize = GOT_PKT_MAX; const unsigned char zero_id[GOT_HASH_DIGEST_MAXLEN] = { 0 }; char old_hashstr[GOT_HASH_DIGEST_STRING_MAXLEN]; char new_hashstr[GOT_HASH_DIGEST_STRING_MAXLEN]; @@ -366,8 +367,12 @@ send_pack(int fd, enum got_hash_algorithm algo, struct if (RB_EMPTY(refs) && RB_EMPTY(delete_refs)) return got_error(GOT_ERR_SEND_EMPTY); + buf = calloc(1, bufsize); + if (buf == NULL) + return got_error_from_errno("calloc"); + while (1) { - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; @@ -526,7 +531,7 @@ send_pack(int fd, enum got_hash_algorithm algo, struct got_hash_digest_to_str(zero_id, new_hashstr, sizeof(new_hashstr), algo); err = describe_refchange(&n, &sent_my_capabilites, - my_capabilities, buf, sizeof(buf), refname, + my_capabilities, buf, bufsize, refname, old_hashstr, new_hashstr); if (err) goto done; @@ -571,7 +576,7 @@ send_pack(int fd, enum got_hash_algorithm algo, struct } got_object_id_hex(id, new_hashstr, sizeof(new_hashstr)); err = describe_refchange(&n, &sent_my_capabilites, - my_capabilities, buf, sizeof(buf), refname, + my_capabilities, buf, bufsize, refname, old_hashstr, new_hashstr); if (err) goto done; @@ -608,7 +613,7 @@ send_pack(int fd, enum got_hash_algorithm algo, struct goto done; } - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, INFTIM); + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; if (n >= 4 && strncmp(buf, "ERR ", 4) == 0) { @@ -621,7 +626,7 @@ send_pack(int fd, enum got_hash_algorithm algo, struct } while (nsent > 0) { - err = got_pkt_readpkt(&n, fd, buf, sizeof(buf), chattygot, + err = got_pkt_readpkt(&n, fd, buf, bufsize, chattygot, INFTIM); if (err) goto done; @@ -659,6 +664,7 @@ done: free(server_capabilities); free(my_capabilities); free(capa); + free(buf); return err; }