Skip to content

Commit

Permalink
Make errors in H replacement more resilient
Browse files Browse the repository at this point in the history
Free the accum_field and subfields always if an error occurs during field replacement (in a list) and they were malloced
  • Loading branch information
Kniggebrot committed Oct 22, 2024
1 parent ad5be5d commit 3ccbfcf
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions ccronexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1339,15 +1339,17 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min
{
char* has_h = strchr(field, 'H');
if (has_h) {
char *accum_field = NULL;
char **subfields = NULL;
size_t subfields_len = 0;
// Check if Field contains ',', if so, split into multiple subfields, and replace in each (with same position no)
char *has_comma = strchr(field, ',');
if (has_comma) {
// Iterate over split sub-fields, check for 'H' and replace if present
size_t subfields_len = 0;
char** subfields = split_str(field, ',', &subfields_len);
subfields = split_str(field, ',', &subfields_len);
if (subfields == NULL) {
*error = "Failed to split 'H' string in list";
return field;
goto return_error;
}
size_t res_len = 0;
size_t res_lens[subfields_len];
Expand All @@ -1357,21 +1359,25 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min
subfields[i] = replace_h_entry(subfields[i], pos, min, error);
}
if (*error != NULL) {
free_splitted(subfields, subfields_len);
return field; // something went wrong trying to replace a subfield
goto return_error;
}
res_lens[i] = strnlen(subfields[i], CRON_MAX_STR_LEN_TO_SPLIT);
res_len += res_lens[i];
}
// Allocate space for the full string: Result lengths + (result count - 1) for the commas + 1 for '\0'
char *accum_field = (char *) cronMalloc(res_len + subfields_len );
accum_field = (char *) cronMalloc(res_len + subfields_len );
if (accum_field == NULL) {
*error = "Failed to merge 'H' in list";
return field;
goto return_error;
}
memset(accum_field, 0, res_len + subfields_len);
char *tracking = accum_field;
for (size_t i = 0; i < subfields_len; i++) {
// Sanity check: Is "tracking" still in the allocated memory boundaries?
if ((tracking - accum_field) > (res_len + subfields_len)) {
*error = "Failed to insert subfields to merged fields: String went oob";
goto return_error;
}
strncpy(tracking, subfields[i], res_lens[i]);
tracking += res_lens[i];
// Don't append comma to last list entry
Expand All @@ -1386,6 +1392,12 @@ static char* check_and_replace_h(char* field, unsigned int pos, unsigned int min
}
// only one H to find and replace, then return
field = replace_h_entry(field, pos, min, error);
return field;

return_error:
if (subfields) free_splitted(subfields, subfields_len);
if (accum_field) cronFree(accum_field);
return field;
}
return field;
}
Expand Down

0 comments on commit 3ccbfcf

Please sign in to comment.