Fix memory leak in pcre2test (found by Coverity Scan).
This commit is contained in:
parent
ba1c759c90
commit
587011e326
|
@ -418,7 +418,7 @@ enum { MOD_CTC, /* Applies to a compile context */
|
||||||
MOD_PDP, /* As MOD_PD, OK for Perl test */
|
MOD_PDP, /* As MOD_PD, OK for Perl test */
|
||||||
MOD_PND, /* As MOD_PD, but not for a default pattern */
|
MOD_PND, /* As MOD_PD, but not for a default pattern */
|
||||||
MOD_PNDP, /* As MOD_PND, OK for Perl test */
|
MOD_PNDP, /* As MOD_PND, OK for Perl test */
|
||||||
MOD_CHR, /* Is a single character */
|
MOD_CHR, /* Is a single character */
|
||||||
MOD_CON, /* Is a "convert" type */
|
MOD_CON, /* Is a "convert" type */
|
||||||
MOD_CTL, /* Is a control bit */
|
MOD_CTL, /* Is a control bit */
|
||||||
MOD_BSR, /* Is a BSR value */
|
MOD_BSR, /* Is a BSR value */
|
||||||
|
@ -519,8 +519,8 @@ typedef struct patctl { /* Structure for pattern modifiers. */
|
||||||
uint32_t stackguard_test;
|
uint32_t stackguard_test;
|
||||||
uint32_t tables_id;
|
uint32_t tables_id;
|
||||||
uint32_t convert_type;
|
uint32_t convert_type;
|
||||||
uint32_t convert_length;
|
uint32_t convert_length;
|
||||||
uint32_t convert_glob_separator;
|
uint32_t convert_glob_separator;
|
||||||
uint32_t regerror_buffsize;
|
uint32_t regerror_buffsize;
|
||||||
uint8_t locale[LOCALESIZE];
|
uint8_t locale[LOCALESIZE];
|
||||||
} patctl;
|
} patctl;
|
||||||
|
@ -728,7 +728,7 @@ static uint32_t exclusive_pat_controls[] = {
|
||||||
CTL_POSIX | CTL_USE_LENGTH,
|
CTL_POSIX | CTL_USE_LENGTH,
|
||||||
CTL_PUSH | CTL_PUSHCOPY,
|
CTL_PUSH | CTL_PUSHCOPY,
|
||||||
CTL_PUSH | CTL_PUSHTABLESCOPY,
|
CTL_PUSH | CTL_PUSHTABLESCOPY,
|
||||||
CTL_PUSHCOPY | CTL_PUSHTABLESCOPY,
|
CTL_PUSHCOPY | CTL_PUSHTABLESCOPY,
|
||||||
CTL_EXPAND | CTL_HEXPAT };
|
CTL_EXPAND | CTL_HEXPAT };
|
||||||
|
|
||||||
/* Data controls that are mutually exclusive. At present these are all in the
|
/* Data controls that are mutually exclusive. At present these are all in the
|
||||||
|
@ -3667,10 +3667,10 @@ for (;;)
|
||||||
}
|
}
|
||||||
pp = ep;
|
pp = ep;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_CHR: /* A single character */
|
case MOD_CHR: /* A single character */
|
||||||
*((uint32_t *)field) = *pp++;
|
*((uint32_t *)field) = *pp++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_CON: /* A convert type */
|
case MOD_CON: /* A convert type */
|
||||||
for (i = 0; i < convertlistcount; i++)
|
for (i = 0; i < convertlistcount; i++)
|
||||||
|
@ -3679,13 +3679,13 @@ for (;;)
|
||||||
{
|
{
|
||||||
if (*((uint32_t *)field) == CONVERT_UNSET)
|
if (*((uint32_t *)field) == CONVERT_UNSET)
|
||||||
*((uint32_t *)field) = convertlist[i].option;
|
*((uint32_t *)field) = convertlist[i].option;
|
||||||
else
|
else
|
||||||
*((uint32_t *)field) |= convertlist[i].option;
|
*((uint32_t *)field) |= convertlist[i].option;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= convertlistcount) goto INVALID_VALUE;
|
if (i >= convertlistcount) goto INVALID_VALUE;
|
||||||
pp = ep;
|
pp = ep;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_IN2: /* One or two unsigned integers */
|
case MOD_IN2: /* One or two unsigned integers */
|
||||||
|
@ -4896,15 +4896,15 @@ if ((pat_patctl.control & CTL_UTF8_INPUT) != 0)
|
||||||
return PR_SKIP;
|
return PR_SKIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The convert and posix modifiers are mutually exclusive. */
|
/* The convert and posix modifiers are mutually exclusive. */
|
||||||
|
|
||||||
if (pat_patctl.convert_type != CONVERT_UNSET &&
|
if (pat_patctl.convert_type != CONVERT_UNSET &&
|
||||||
(pat_patctl.control & CTL_POSIX) != 0)
|
(pat_patctl.control & CTL_POSIX) != 0)
|
||||||
{
|
{
|
||||||
fprintf(outfile, "** The convert and posix modifiers are mutually exclusive\n");
|
fprintf(outfile, "** The convert and posix modifiers are mutually exclusive\n");
|
||||||
return PR_SKIP;
|
return PR_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for mutually exclusive control modifiers. At present, these are all in
|
/* Check for mutually exclusive control modifiers. At present, these are all in
|
||||||
the first control word. */
|
the first control word. */
|
||||||
|
@ -5310,60 +5310,71 @@ it ends up back in the usual place. */
|
||||||
if (pat_patctl.convert_type != CONVERT_UNSET)
|
if (pat_patctl.convert_type != CONVERT_UNSET)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
int convert_return = PR_OK;
|
||||||
uint32_t convert_options = pat_patctl.convert_type;
|
uint32_t convert_options = pat_patctl.convert_type;
|
||||||
void *converted_pattern;
|
void *converted_pattern;
|
||||||
PCRE2_SIZE converted_length;
|
PCRE2_SIZE converted_length;
|
||||||
|
|
||||||
if (pat_patctl.convert_length != 0)
|
if (pat_patctl.convert_length != 0)
|
||||||
{
|
{
|
||||||
converted_length = pat_patctl.convert_length;
|
converted_length = pat_patctl.convert_length;
|
||||||
converted_pattern = malloc(converted_length * code_unit_size);
|
converted_pattern = malloc(converted_length * code_unit_size);
|
||||||
if (converted_pattern == NULL)
|
if (converted_pattern == NULL)
|
||||||
{
|
{
|
||||||
fprintf(outfile, "** Failed: malloc failed for converted pattern\n");
|
fprintf(outfile, "** Failed: malloc failed for converted pattern\n");
|
||||||
return PR_SKIP;
|
return PR_SKIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else converted_pattern = NULL; /* Let the library allocate */
|
else converted_pattern = NULL; /* Let the library allocate */
|
||||||
|
|
||||||
if (utf) convert_options |= PCRE2_CONVERT_UTF;
|
if (utf) convert_options |= PCRE2_CONVERT_UTF;
|
||||||
if ((pat_patctl.options & PCRE2_NO_UTF_CHECK) != 0)
|
if ((pat_patctl.options & PCRE2_NO_UTF_CHECK) != 0)
|
||||||
convert_options |= PCRE2_CONVERT_NO_UTF_CHECK;
|
convert_options |= PCRE2_CONVERT_NO_UTF_CHECK;
|
||||||
|
|
||||||
CONCTXCPY(con_context, default_con_context);
|
CONCTXCPY(con_context, default_con_context);
|
||||||
if (pat_patctl.convert_glob_separator != 0)
|
if (pat_patctl.convert_glob_separator != 0)
|
||||||
{
|
{
|
||||||
PCRE2_SET_GLOB_SEPARATOR(rc, con_context, pat_patctl.convert_glob_separator);
|
PCRE2_SET_GLOB_SEPARATOR(rc, con_context, pat_patctl.convert_glob_separator);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
{
|
{
|
||||||
fprintf(outfile, "** Invalid glob separator '%c'\n",
|
fprintf(outfile, "** Invalid glob separator '%c'\n",
|
||||||
pat_patctl.convert_glob_separator);
|
pat_patctl.convert_glob_separator);
|
||||||
return PR_SKIP;
|
convert_return = PR_SKIP;
|
||||||
}
|
goto CONVERT_FINISH;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PCRE2_PATTERN_CONVERT(rc, pbuffer, patlen, convert_options,
|
|
||||||
|
PCRE2_PATTERN_CONVERT(rc, pbuffer, patlen, convert_options,
|
||||||
&converted_pattern, &converted_length, con_context);
|
&converted_pattern, &converted_length, con_context);
|
||||||
|
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
{
|
{
|
||||||
fprintf(outfile, "** Pattern conversion error at offset %lu: ",
|
fprintf(outfile, "** Pattern conversion error at offset %lu: ",
|
||||||
converted_length);
|
converted_length);
|
||||||
if (!print_error_message(rc, "", "\n")) return PR_ABEND;
|
convert_return = print_error_message(rc, "", "\n")? PR_SKIP:PR_ABEND;
|
||||||
return PR_SKIP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output the converted pattern, copy it, then free it. */
|
/* Output the converted pattern, then copy it. */
|
||||||
|
|
||||||
PCHARSV(converted_pattern, 0, converted_length, utf, outfile);
|
else
|
||||||
fprintf(outfile, "\n");
|
{
|
||||||
|
PCHARSV(converted_pattern, 0, converted_length, utf, outfile);
|
||||||
patlen = converted_length;
|
fprintf(outfile, "\n");
|
||||||
CONVERT_COPY(pbuffer, converted_pattern, converted_length + 1);
|
patlen = converted_length;
|
||||||
|
CONVERT_COPY(pbuffer, converted_pattern, converted_length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the converted pattern. */
|
||||||
|
|
||||||
|
CONVERT_FINISH:
|
||||||
if (pat_patctl.convert_length != 0)
|
if (pat_patctl.convert_length != 0)
|
||||||
free(converted_pattern);
|
free(converted_pattern);
|
||||||
else
|
else
|
||||||
PCRE2_CONVERTED_PATTERN_FREE(converted_pattern);
|
PCRE2_CONVERTED_PATTERN_FREE(converted_pattern);
|
||||||
|
|
||||||
|
/* Return if conversion was unsuccessful. */
|
||||||
|
|
||||||
|
if (convert_return != PR_OK) return convert_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* By default we pass a zero-terminated pattern, but a length is passed if
|
/* By default we pass a zero-terminated pattern, but a length is passed if
|
||||||
|
|
Loading…
Reference in New Issue