imap-send: increase command size limit
nfvasprintf() has a 8KB limit, but it's not relevant, as its result is combined with other strings and added to a 1KB buffer by its caller. That 1KB limit is not mentioned in RFC 9051, which specifies IMAP. While 1KB is plenty for user names, passwords and mailbox names, there's no point in limiting our commands like that. Call xstrvfmt() instead of open-coding it and use strbuf to format the command to send, as we need its length. Fail hard if it exceeds INT_MAX, because socket_write() can't take more than that. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Apr 14, 2024 at 18:47 UTC
21b5821acd6a5627d2efcc22021f8f040373a69c
1 file changed
+12
-23
imap-send.c
+12
-23
@@ -68,20 +68,6 @@ static void imap_warn(const char *, ...);
68
69
static char *next_arg(char **);
70
71
-static int nfvasprintf(char **strp, const char *fmt, va_list ap)
72
-{
73
- int len;
74
- char tmp[8192];
75
-
76
- len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
77
- if (len < 0)
78
- die("Fatal: Out of memory");
79
- if (len >= sizeof(tmp))
80
- die("imap command overflow!");
81
- *strp = xmemdupz(tmp, len);
82
- return len;
83
-}
84
-
71
struct imap_server_conf {
72
const char *name;
73
const char *tunnel;
@@ -503,11 +489,11 @@ static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
489
{
490
struct imap *imap = ctx->imap;
491
struct imap_cmd *cmd;
506
- int n, bufl;
507
- char buf[1024];
492
+ int n;
493
+ struct strbuf buf = STRBUF_INIT;
494
495
cmd = xmalloc(sizeof(struct imap_cmd));
510
- nfvasprintf(&cmd->cmd, fmt, ap);
496
+ cmd->cmd = xstrvfmt(fmt, ap);
497
cmd->tag = ++imap->nexttag;
498
499
if (cb)
@@ -519,27 +505,30 @@ static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
505
get_cmd_result(ctx, NULL);
506
507
if (!cmd->cb.data)
522
- bufl = xsnprintf(buf, sizeof(buf), "%d %s\r\n", cmd->tag, cmd->cmd);
508
+ strbuf_addf(&buf, "%d %s\r\n", cmd->tag, cmd->cmd);
509
else
524
- bufl = xsnprintf(buf, sizeof(buf), "%d %s{%d%s}\r\n",
525
- cmd->tag, cmd->cmd, cmd->cb.dlen,
526
- CAP(LITERALPLUS) ? "+" : "");
510
+ strbuf_addf(&buf, "%d %s{%d%s}\r\n", cmd->tag, cmd->cmd,
511
+ cmd->cb.dlen, CAP(LITERALPLUS) ? "+" : "");
512
+ if (buf.len > INT_MAX)
513
+ die("imap command overflow!");
514
515
if (0 < verbosity) {
516
if (imap->num_in_progress)
517
printf("(%d in progress) ", imap->num_in_progress);
518
if (!starts_with(cmd->cmd, "LOGIN"))
532
- printf(">>> %s", buf);
519
+ printf(">>> %s", buf.buf);
520
else
521
printf(">>> %d LOGIN <user> <pass>\n", cmd->tag);
522
}
536
- if (socket_write(&imap->buf.sock, buf, bufl) != bufl) {
523
+ if (socket_write(&imap->buf.sock, buf.buf, buf.len) != buf.len) {
524
free(cmd->cmd);
525
free(cmd);
526
if (cb)
527
free(cb->data);
528
+ strbuf_release(&buf);
529
return NULL;
530
}
531
+ strbuf_release(&buf);
532
if (cmd->cb.data) {
533
if (CAP(LITERALPLUS)) {
534
n = socket_write(&imap->buf.sock, cmd->cb.data, cmd->cb.dlen);