Skip to content

Commit 44b42e1

Browse files
committed
mod_mail: Use unsigned long instead of unsigned int for quota.
Use unsigned long for quota so that we can internally keep track of quotas larger than ~4GB. We were already using unsigned long for the quota APIs, but internally were only using an unsigned int, which led to overflow with larger values.
1 parent 58af100 commit 44b42e1

File tree

1 file changed

+19
-13
lines changed

1 file changed

+19
-13
lines changed

modules/mod_mail.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@
4949

5050
static char root_maildir[248] = "";
5151
static char catchall[256] = "";
52-
static unsigned int maxquota = 10000000;
52+
static unsigned long maxquota = 10000000;
5353

5454
struct stringlist local_domains;
5555

5656
/*! \brief Opaque structure for a user's mailbox */
5757
struct mailbox {
5858
unsigned int id; /* Mailbox ID. Corresponds with user ID. */
5959
unsigned int watchers; /* Number of watchers for this mailbox. */
60-
unsigned int quota; /* Total quota for this mailbox */
61-
unsigned int quotausage; /* Cached quota usage calculation */
60+
unsigned long quota; /* Total quota for this mailbox */
61+
unsigned long quotausage; /* Cached quota usage calculation */
6262
char maildir[266]; /* User's mailbox directory, on disk. */
6363
size_t maildirlen; /* Length of maildir */
6464
bbs_rwlock_t lock; /* R/W lock for entire mailbox. R/W instead of a mutex, because POP write locks the entire mailbox, IMAP can just read lock. */
@@ -804,11 +804,11 @@ void mailbox_quota_adjust_usage(struct mailbox *mbox, int bytes)
804804
{
805805
mailbox_uid_lock(mbox); /* Borrow the UID lock since we need to do this atomically */
806806
if (mbox->quotavalid) {
807-
mbox->quotausage += (unsigned int) bytes;
807+
mbox->quotausage += (unsigned long) bytes;
808808
if (mbox->quotausage > mailbox_quota(mbox)) {
809809
/* Could also happen if we underflow below 0, since quotausage is unsigned */
810810
/* Either our adjustments to the cached value went off somewhere, or we didn't check the quota somewhere. Either way, somebody screwed up. */
811-
bbs_error("Mailbox quota usage (%u) exceeds quota allowed (%lu)\n", mbox->quotausage, mailbox_quota(mbox));
811+
bbs_error("Mailbox quota usage (%lu) exceeds quota allowed (%lu)\n", mbox->quotausage, mailbox_quota(mbox));
812812
mailbox_invalidate_quota_cache(mbox);
813813
}
814814
}
@@ -829,10 +829,10 @@ unsigned long mailbox_quota(struct mailbox *mbox)
829829
snprintf(quotafile, sizeof(quotafile), "%s/.quota", mailbox_maildir(mbox));
830830
fp = fopen(quotafile, "r");
831831
if (fp && fgets(quotabuf, sizeof(quotabuf), fp)) { /* Use the default */
832-
mbox->quota = (unsigned int) atoi(quotabuf);
832+
mbox->quota = (unsigned long) atol(quotabuf);
833833
fclose(fp);
834834
} else {
835-
mbox->quota = (unsigned int) maxquota;
835+
mbox->quota = maxquota;
836836
if (fp) {
837837
fclose(fp);
838838
}
@@ -857,7 +857,7 @@ unsigned long mailbox_quota_used(struct mailbox *mbox)
857857
return 0;
858858
}
859859
quotaused = (unsigned long) tmp;
860-
mbox->quotausage = (unsigned int) quotaused;
860+
mbox->quotausage = quotaused;
861861
mbox->quotavalid = 1; /* This can be cached until invalidated again */
862862
return quotaused;
863863
}
@@ -874,7 +874,7 @@ unsigned long mailbox_quota_remaining(struct mailbox *mbox)
874874
if (quota > mbox->quotausage) {
875875
return quota - mbox->quotausage;
876876
}
877-
bbs_debug(5, "No quota remaining in this mailbox (%u used, %lu available)\n", mbox->quotausage, quota);
877+
bbs_debug(5, "No quota remaining in this mailbox (%lu used, %lu available)\n", mbox->quotausage, quota);
878878
return 0; /* Already over quota */
879879
}
880880

@@ -886,15 +886,15 @@ unsigned long mailbox_quota_remaining(struct mailbox *mbox)
886886
return quota;
887887
}
888888
quotaused = (unsigned long) tmp;
889-
mbox->quotausage = (unsigned int) quotaused;
889+
mbox->quotausage = quotaused;
890890
mbox->quotavalid = 1; /* This can be cached until invalidated again */
891891
if (quotaused >= quota) {
892892
bbs_debug(5, "No quota remaining in this mailbox (%lu used, %lu available)\n", quotaused, quota);
893893
mbox->overquota = 1;
894894
return 0; /* Quota already exceeded. Don't cast to unsigned or it will underflow and be huge. */
895895
}
896896
quota -= quotaused;
897-
return (unsigned long) (quota - quotaused);
897+
return (quota - quotaused);
898898
}
899899

900900
#define MAX_UID 4294967295
@@ -2207,7 +2207,7 @@ static int cli_mailbox(struct bbs_cli_args *a)
22072207
bbs_dprintf(a->fdout, "%-20s: %9lu KB\n", "Quota Used", mailbox_quota_used(mbox) / 1024);
22082208
bbs_dprintf(a->fdout, "%-20s: %9lu KB\n", "Quota Remaining", mailbox_quota_remaining(mbox) / 1024);
22092209
bbs_dprintf(a->fdout, "%-20s: %u\n", "# Mailbox Watchers", mbox->watchers);
2210-
bbs_dprintf(a->fdout, "%-20s: %s\n", "Activity Pending", BBS_YN(mbox->activity));
2210+
bbs_dprintf(a->fdout, "%-20s: %s\n", "Activity Pending", BBS_YESNO(mbox->activity));
22112211
return 0;
22122212
}
22132213

@@ -2221,6 +2221,7 @@ static int load_config(void)
22212221
struct bbs_config *cfg;
22222222
struct bbs_config_section *section = NULL;
22232223
struct bbs_keyval *keyval = NULL;
2224+
const char *tmp;
22242225

22252226
cfg = bbs_config_load("mod_mail.conf", 1);
22262227
if (!cfg) {
@@ -2232,7 +2233,12 @@ static int load_config(void)
22322233
return -1;
22332234
}
22342235
bbs_config_val_set_str(cfg, "general", "catchall", catchall, sizeof(catchall));
2235-
bbs_config_val_set_uint(cfg, "general", "quota", &maxquota);
2236+
2237+
/* Don't use bbs_config_val_set_uint, since we need to parse as long, not int */
2238+
tmp = bbs_config_val(cfg, "general", "quota");
2239+
if (!strlen_zero(tmp)) {
2240+
maxquota = (unsigned long) atol(tmp);
2241+
}
22362242

22372243
if (eaccess(root_maildir, X_OK)) { /* This is a directory, so we better have execute permissions on it */
22382244
bbs_error("Directory %s does not exist\n", root_maildir);

0 commit comments

Comments
 (0)