Skip to content

Commit f090ec6

Browse files
committed
carddav_db.c: avoid memory corruption due to overrunning ring buffer
1 parent ec54544 commit f090ec6

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

Diff for: imap/carddav_db.c

+24-6
Original file line numberDiff line numberDiff line change
@@ -1141,9 +1141,7 @@ EXPORTED int carddav_writecard(struct carddav_db *carddavdb,
11411141
else if (!strcasecmp(name, "nickname")) {
11421142
if (buf_len(&nicknames)) buf_putc(&nicknames, ',');
11431143
buf_appendcstr(&nicknames, propval);
1144-
cdata->nickname = buf_cstring(&nicknames);;
1145-
strarray_appendm(&values, propval);
1146-
propval = NULL;
1144+
cdata->nickname = buf_cstring(&nicknames);
11471145
}
11481146
else if (!strcasecmp(name, "email")) {
11491147
/* XXX - insert if primary */
@@ -1420,33 +1418,49 @@ EXPORTED int carddav_writecard_x(struct carddav_db *carddavdb,
14201418
int ispinned)
14211419
{
14221420
struct buf nicknames = BUF_INITIALIZER;
1421+
strarray_t values = STRARRAY_INITIALIZER;
14231422
strarray_t emails = STRARRAY_INITIALIZER;
14241423
strarray_t member_uids = STRARRAY_INITIALIZER;
14251424
vcardproperty *prop;
14261425

14271426
for (prop = vcardcomponent_get_first_property(vcard, VCARD_ANY_PROPERTY);
14281427
prop;
14291428
prop = vcardcomponent_get_next_property(vcard, VCARD_ANY_PROPERTY)) {
1430-
const char *propval = vcardproperty_get_value_as_string(prop);
1429+
/* The libical BUFFER_RING_SIZE used by *_get_value_as_string()
1430+
* is 2500 entries.
1431+
* A vCard with more than 2500 properties (E.g. a large group card)
1432+
* will cause some of our value pointers to be freed out from under us.
1433+
* So, we use vcardproperty_get_value_as_string_r() here instead
1434+
* and manage the memory ourselves.
1435+
*/
1436+
char *propval = vcardproperty_get_value_as_string_r(prop);
14311437
const char *userid = "";
14321438

1439+
if (!propval) continue;
1440+
14331441
switch (vcardproperty_isa(prop)) {
14341442
case VCARD_UID_PROPERTY:
14351443
cdata->vcard_uid = propval;
1444+
strarray_appendm(&values, propval);
1445+
propval = NULL;
14361446
break;
14371447

14381448
case VCARD_N_PROPERTY:
14391449
cdata->name = propval;
1450+
strarray_appendm(&values, propval);
1451+
propval = NULL;
14401452
break;
14411453

14421454
case VCARD_FN_PROPERTY:
14431455
cdata->fullname = propval;
1456+
strarray_appendm(&values, propval);
1457+
propval = NULL;
14441458
break;
14451459

14461460
case VCARD_NICKNAME_PROPERTY:
14471461
if (buf_len(&nicknames)) buf_putc(&nicknames, ',');
14481462
buf_appendcstr(&nicknames, propval);
1449-
cdata->nickname = buf_cstring(&nicknames);;
1463+
cdata->nickname = buf_cstring(&nicknames);
14501464
break;
14511465

14521466
case VCARD_EMAIL_PROPERTY: {
@@ -1471,8 +1485,9 @@ EXPORTED int carddav_writecard_x(struct carddav_db *carddavdb,
14711485
}
14721486
}
14731487
}
1474-
strarray_append(&emails, propval);
1488+
strarray_appendm(&emails, propval);
14751489
strarray_append(&emails, ispref ? "1" : "");
1490+
propval = NULL;
14761491
break;
14771492
}
14781493

@@ -1511,6 +1526,8 @@ EXPORTED int carddav_writecard_x(struct carddav_db *carddavdb,
15111526
default:
15121527
break;
15131528
}
1529+
1530+
free(propval);
15141531
}
15151532

15161533
int r;
@@ -1529,6 +1546,7 @@ EXPORTED int carddav_writecard_x(struct carddav_db *carddavdb,
15291546
if (!r) r = carddav_write_groups(carddavdb, cdata->dav.rowid, &member_uids);
15301547

15311548
buf_free(&nicknames);
1549+
strarray_fini(&values);
15321550
strarray_fini(&emails);
15331551
strarray_fini(&member_uids);
15341552

0 commit comments

Comments
 (0)