[libical] Fix sec issues and update from upstream

* Bug 1275400 - Porting upstream fixes for use-after-free vulnerability of libical.
* Bug 1553814 - Heap buffer overflow in icalvalue.c icalmemory_strdup_and_dequote.
* Bug 1553808 - Update libical from upstream.
* Bug 1553820 - Update libical from upstream. & Follow-up. (libcal)
* Bug 1555646 - Update libical from upstream.
custom-2020
g4jc 3 years ago committed by Roy Tam
parent f4d1562ae5
commit e9192b0559
  1. 133
      modules/libical/src/libical/icalparser.c
  2. 11
      modules/libical/src/libical/icalrecur.c
  3. 20
      modules/libical/src/libical/icaltime.c
  4. 2
      modules/libical/src/libical/icaltypes.c
  5. 135
      modules/libical/src/libical/icalvalue.c

@ -190,25 +190,24 @@ static
char* parser_get_next_char(char c, char *str, int qm)
{
int quote_mode = 0;
char* p;
for(p=str; *p!=0; p++){
if (qm == 1) {
if ( quote_mode == 0 && *p=='"' && *(p-1) != '\\' ){
quote_mode =1;
continue;
}
if ( quote_mode == 1 && *p=='"' && *(p-1) != '\\' ){
quote_mode =0;
continue;
}
}
if (quote_mode == 0 && *p== c && *(p-1) != '\\' ){
return p;
}
char *p = str;
char next_char = *p;
char prev_char = 0;
while (next_char != '\0') {
if (prev_char != '\\') {
if (qm == 1 && next_char == '"') {
/* Encountered a quote, toggle quote mode */
quote_mode = !quote_mode;
} else if (quote_mode == 0 && next_char == c) {
/* Found a matching character out of quote mode, return it */
return p;
}
}
/* Save the previous character so we can check if it's a backslash in the next iteration */
prev_char = next_char;
next_char = *(++p);
}
return 0;
@ -382,10 +381,9 @@ char* parser_get_next_value(char* line, char **end, icalvalue_kind kind)
/* If the comma is preceded by a '\', then it is a literal and
not a value separator*/
if ( (next!=0 && *(next-1) == '\\') ||
(next!=0 && *(next-3) == '\\')
)
/*second clause for '/' is on prev line. HACK may be out of bounds */
if ((next!=0 && *(next-1) == '\\') ||
(next!=0 && (next-3) >= line && *(next-3) == '\\' && *(next-2) == '\r' && *(next-1) == '\n'))
/* second clause for '\' is on prev line */
{
p = next+1;
} else {
@ -731,24 +729,10 @@ icalcomponent* icalparser_add_line(icalparser* parser,
parser->level++;
str = parser_get_next_value(end,&end, value_kind);
comp_kind = icalenum_string_to_component_kind(str);
if (comp_kind == ICAL_NO_COMPONENT){
comp_kind = icalenum_string_to_component_kind(str);
c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT);
insert_error(c,str,"Parse error in component name",
ICAL_XLICERRORTYPE_COMPONENTPARSEERROR);
}
if (comp_kind != ICAL_X_COMPONENT) {
c = icalcomponent_new(comp_kind);
} else {
c = icalcomponent_new_x(str);
}
c = icalcomponent_new(comp_kind);
if (c == 0){
c = icalcomponent_new(ICAL_XLICINVALID_COMPONENT);
@ -984,6 +968,12 @@ icalcomponent* icalparser_add_line(icalparser* parser,
/* If it is a VALUE parameter, set the kind of value*/
if (icalparameter_isa(param)==ICAL_VALUE_PARAMETER){
const char unknown_type[] =
"Got a VALUE parameter with an unknown type";
const char illegal_type[] =
"Got a VALUE parameter with an illegal type for property";
const char *value_err = NULL;
value_kind = (icalvalue_kind)
icalparameter_value_to_value_kind(
@ -995,10 +985,69 @@ icalcomponent* icalparser_add_line(icalparser* parser,
/* Ooops, could not parse the value of the
parameter ( it was not one of the defined
values ), so reset the value_kind */
insert_error(
tail, str,
"Got a VALUE parameter with an unknown type",
value_err = unknown_type;
}
else if (value_kind !=
icalproperty_kind_to_value_kind(icalproperty_isa(prop))) {
/* VALUE parameter type does not match default type
for this property (check for allowed alternate types) */
switch (prop_kind) {
case ICAL_ATTACH_PROPERTY:
// case ICAL_IMAGE_PROPERTY:
/* Accept BINARY */
if (value_kind != ICAL_BINARY_VALUE)
value_err = illegal_type;
break;
case ICAL_DTEND_PROPERTY:
case ICAL_DUE_PROPERTY:
case ICAL_DTSTART_PROPERTY:
case ICAL_EXDATE_PROPERTY:
case ICAL_RECURRENCEID_PROPERTY:
/* Accept DATE */
if (value_kind != ICAL_DATE_VALUE)
value_err = illegal_type;
break;
case ICAL_GEO_PROPERTY:
/* Accept FLOAT (but change to GEO) */
if (value_kind != ICAL_FLOAT_VALUE)
value_err = illegal_type;
else value_kind = ICAL_GEO_VALUE;
break;
case ICAL_RDATE_PROPERTY:
/* Accept DATE-TIME, DATE or PERIOD */
if (value_kind != ICAL_DATETIME_VALUE &&
value_kind != ICAL_DATE_VALUE &&
value_kind != ICAL_PERIOD_VALUE)
value_err = illegal_type;
break;
case ICAL_TRIGGER_PROPERTY:
/* Accept DATE-TIME */
if (value_kind != ICAL_DATETIME_VALUE)
value_err = illegal_type;
break;
case ICAL_X_PROPERTY:
/* Accept ANY value type */
break;
default:
/* ONLY default type is allowed */
value_err = illegal_type;
break;
}
}
if (value_err != NULL) {
/* Ooops, unknown/illegal VALUE parameter,
so reset the value_kind */
insert_error(tail, str, value_err,
ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR);
value_kind =

@ -404,10 +404,15 @@ void icalrecur_add_bydayrules(struct icalrecur_parser *parser, const char* vals)
wd = icalrecur_string_to_weekday(t);
if (wd != ICAL_NO_WEEKDAY) {
array[i++] = (short) (sign * (wd + 8 * weekno));
array[i] = ICAL_RECURRENCE_ARRAY_MAX;
/* Sanity check value */
if (wd == ICAL_NO_WEEKDAY || weekno >= ICAL_BY_WEEKNO_SIZE) {
free(vals_copy);
return;
}
int position = sign * weekno;
array[i++] = (wd + (8 * abs(position))) * ((position < 0) ? -1 : 1);
array[i] = ICAL_RECURRENCE_ARRAY_MAX;
}
free(vals_copy);

@ -517,20 +517,20 @@ struct icaltimetype icaltime_from_string(const char* str)
size = strlen(str);
if ((size == 15) || (size == 19)) { /* floating time with/without separators*/
tt.is_utc = 0;
tt.is_date = 0;
tt.is_utc = 0;
tt.is_date = 0;
} else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z'*/
if ((str[15] != 'Z') && (str[19] != 'Z'))
goto FAIL;
if ((str[size-1] != 'Z'))
goto FAIL;
tt.is_utc = 1;
tt.zone = icaltimezone_get_utc_timezone();
tt.is_date = 0;
tt.is_utc = 1;
tt.zone = icaltimezone_get_utc_timezone();
tt.is_date = 0;
} else if ((size == 8) || (size == 10)) { /* A DATE */
tt.is_utc = 0;
tt.is_date = 1;
tt.is_utc = 0;
tt.is_date = 1;
} else { /* error */
goto FAIL;
goto FAIL;
}
if (tt.is_date == 1){

@ -166,7 +166,7 @@ struct icalreqstattype icalreqstattype_from_string(const char* str)
p2 = strchr(p1+1,';');
if (p2 != 0 && *p2 != 0){
stat.debug = p2+1;
stat.debug = icalmemory_tmp_copy(p2 + 1);
}
return stat;

@ -189,77 +189,80 @@ icalvalue* icalvalue_new_clone(const icalvalue* old) {
static char* icalmemory_strdup_and_dequote(const char* str)
{
const char* p;
char* out = (char*)malloc(sizeof(char) * strlen(str) +1);
char* pout;
const char *p;
char *out = (char *)malloc(sizeof(char) * strlen(str) + 1);
char *pout;
int wroteNull = 0;
if (out == 0){
return 0;
if (out == 0) {
return 0;
}
pout = out;
for (p = str; *p!=0; p++){
if( *p == '\\')
{
p++;
switch(*p){
case 0:
{
*pout = '\0';
break;
}
case 'n':
case 'N':
{
*pout = '\n';
break;
}
case 't':
case 'T':
{
*pout = '\t';
break;
}
case 'r':
case 'R':
{
*pout = '\r';
break;
}
case 'b':
case 'B':
{
*pout = '\b';
break;
}
case 'f':
case 'F':
{
*pout = '\f';
break;
}
case ';':
case ',':
case '"':
case '\\':
{
*pout = *p;
break;
}
default:
{
*pout = ' ';
}
}
} else {
*pout = *p;
}
/* Stop the loop when encountering a terminator in the source string
or if a null has been written to the destination. This prevents
reading past the end of the source string if the last character
is a backslash. */
for (p = str; !wroteNull && *p != 0; p++) {
if (*p == '\\') {
p++;
switch (*p) {
case 0:
{
wroteNull = 1; //stops iteration so p isn't incremented past the end of str
*pout = '\0';
break;
}
case 'n':
case 'N':
{
*pout = '\n';
break;
}
case 't':
case 'T':
{
*pout = '\t';
break;
}
case 'r':
case 'R':
{
*pout = '\r';
break;
}
case 'b':
case 'B':
{
*pout = '\b';
break;
}
case 'f':
case 'F':
{
*pout = '\f';
break;
}
case ';':
case ',':
case '"':
case '\\':
{
*pout = *p;
break;
}
default:
{
*pout = ' ';
}
}
} else {
*pout = *p;
}
pout++;
pout++;
}
*pout = '\0';
@ -267,6 +270,8 @@ static char* icalmemory_strdup_and_dequote(const char* str)
return out;
}
/*
* Returns a quoted copy of a string
*/

Loading…
Cancel
Save