чување 1cee24c2cfa9b8a9ea98dc5a1cb9746819677d6c
родитељ 42ef2d1df0c14cd0d37c26429cee6cd7f61eb9d6
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Sun, 28 Mar 2021 20:44:37 +0200
Fixed actual leaks
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
| M | TODO | | | 6 | +++--- |
| M | slw2gmi.c | | | 273 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
измењених датотека: 2, додавања: 170(+), брисања: 109(-)
diff --git a/TODO b/TODO
@@ -2,7 +2,7 @@
TODO
====
- [ ] Fix leaks
- [ ] Fix leaks in slw2gmi
- [ ] Propagate the fixes to slweb
+ [x] Fix leaks
+ [x] Fix leaks in slw2gmi
+ [x] Propagate the fixes to slweb
diff --git a/slw2gmi.c b/slw2gmi.c
@@ -146,6 +146,9 @@ free_keyvalue(KeyValue** list, size_t list_count)
}
int
+slweb_cleanup();
+
+int
slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links);
char*
@@ -185,6 +188,8 @@ startswith(const char* s, const char* what)
uint8_t*
get_value(KeyValue* list, size_t list_count, uint8_t* key, BOOL* seen)
{
+ if (!list)
+ return NULL;
KeyValue* plist = list;
while (plist < list + list_count)
{
@@ -881,31 +886,27 @@ process_include(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links)
read_file_into_buffer(&buffer, &buffer_size, input_filename,
&input_dirname, &input);
+ free_keyvalue(&links, links_count);
free(links);
- CALLOC(links, KeyValue, 1)
- links->key = NULL;
- links->value = NULL;
- links->value_size = 0;
+ links = NULL;
links_count = 0;
+ free_keyvalue(¶links, paralinks_count);
free(paralinks);
- CALLOC(paralinks, KeyValue, 1)
- paralinks->key = NULL;
- paralinks->value = NULL;
- paralinks->value_size = 0;
+ paralinks = NULL;
paralinks_count = 0;
+ free_keyvalue(&footnotes, footnote_count);
free(footnotes);
- CALLOC(footnotes, KeyValue, 1)
- footnotes->key = NULL;
- footnotes->value = NULL;
- footnotes->value_size = 0;
+ footnotes = NULL;
footnote_count = 0;
current_footnote = 0;
- free(inline_footnotes);
- CALLOC(inline_footnotes, uint8_t*, 1)
- *inline_footnotes = NULL;
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ inline_footnotes = NULL;
inline_footnote_count = 0;
current_inline_footnote = 0;
@@ -921,7 +922,7 @@ process_include(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links)
if (result)
{
- free(input_filename);
+ slweb_cleanup();
free(buffer);
return result;
}
@@ -938,7 +939,7 @@ process_include(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links)
output_firstcol = saved_output_firstcol;
skip_para_end = saved_skip_para_end;
- free(input_filename);
+ slweb_cleanup();
free(buffer);
exit(result);
}
@@ -1107,31 +1108,27 @@ process_incdir_subdir(const char* subdirname, const uint8_t* link_prefix,
read_file_into_buffer(&buffer, &buffer_size, input_filename,
&input_dirname, &input);
+ free_keyvalue(&links, links_count);
free(links);
- CALLOC(links, KeyValue, 1)
- links->key = NULL;
- links->value = NULL;
- links->value_size = 0;
+ links = NULL;
links_count = 0;
+ free_keyvalue(¶links, paralinks_count);
free(paralinks);
- CALLOC(paralinks, KeyValue, 1)
- paralinks->key = NULL;
- paralinks->value = NULL;
- paralinks->value_size = 0;
+ paralinks = 0;
paralinks_count = 0;
+ free_keyvalue(&footnotes, footnote_count);
free(footnotes);
- CALLOC(footnotes, KeyValue, 1)
- footnotes->key = NULL;
- footnotes->value = NULL;
- footnotes->value_size = 0;
+ footnotes = 0;
footnote_count = 0;
current_footnote = 0;
- free(inline_footnotes);
- CALLOC(inline_footnotes, uint8_t*, 1)
- *inline_footnotes = NULL;
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ inline_footnotes = NULL;
inline_footnote_count = 0;
current_inline_footnote = 0;
@@ -1147,6 +1144,7 @@ process_incdir_subdir(const char* subdirname, const uint8_t* link_prefix,
if (result)
{
+ slweb_cleanup();
free(buffer);
free(link);
free(basename);
@@ -1168,6 +1166,7 @@ process_incdir_subdir(const char* subdirname, const uint8_t* link_prefix,
skip_para_end = saved_skip_para_end;
fflush(output);
+ slweb_cleanup();
free(buffer);
free(link);
free(basename);
@@ -1208,9 +1207,8 @@ process_incdir(uint8_t* token, const uint8_t* link_prefix, FILE* output,
long num = 5;
uint8_t* macro_body = NULL;
int names_total = 0;
+ int current_name = 0;
struct dirent** namelist;
- struct dirent** pnamelist;
- long names_output;
BOOL details_open = TRUE;
@@ -1273,16 +1271,16 @@ process_incdir(uint8_t* token, const uint8_t* link_prefix, FILE* output,
exit(error(errno, (uint8_t*)"incdir: scandir '%s' error", incdir));
}
- pnamelist = namelist;
- names_output = 0;
+ current_name = 0;
print_output(output, "\n");
- while (names_output < num && pnamelist && *pnamelist)
+ if (names_total < num)
+ num = names_total;
+ while (current_name < num)// && pnamelist && *pnamelist)
{
- process_incdir_subdir((*pnamelist)->d_name, link_prefix, output,
- details_open, macro_body);
+ process_incdir_subdir(namelist[current_name]->d_name, link_prefix,
+ output, details_open, macro_body);
details_open = FALSE;
- pnamelist++;
- names_output++;
+ current_name++;
}
print_output(output, "\n");
output_firstcol = TRUE;
@@ -1408,7 +1406,12 @@ process_macro(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links,
{
macros_count++;
- if (macros_count > 1)
+ if (!macros)
+ {
+ CALLOC(macros, KeyValue, macros_count)
+ pmacros = macros;
+ }
+ else
{
REALLOC(macros, KeyValue, macros_count * sizeof(KeyValue))
pmacros = macros + macros_count - 1;
@@ -1711,10 +1714,7 @@ process_paralinks(const uint8_t* link_prefix, FILE* output)
free_keyvalue(¶links, paralinks_count);
free(paralinks);
- CALLOC(paralinks, KeyValue, 1)
- paralinks->key = NULL;
- paralinks->value = NULL;
- paralinks->value_size = 0;
+ paralinks = NULL;
paralinks_count = 0;
pparalinks = paralinks;
@@ -1826,7 +1826,12 @@ process_inline_footnote(uint8_t* token, BOOL read_yaml_macros_and_links,
inline_footnote_count++;
if (inline_footnote_count == 1 && footnote_count > 0)
warning(1, (uint8_t*)"Both inline and regular footnotes present");
- else if (inline_footnote_count > 1)
+ else if (!inline_footnotes)
+ {
+ inline_footnote_count = 1;
+ CALLOC(inline_footnotes, uint8_t*, inline_footnote_count)
+ }
+ else
REALLOC(inline_footnotes, uint8_t*, sizeof(uint8_t*) * inline_footnote_count)
CALLOC(inline_footnotes[inline_footnote_count-1], uint8_t, token_len+1)
@@ -1853,9 +1858,14 @@ process_footnote(uint8_t* token, BOOL footnote_definition, BOOL footnote_output,
footnote_count++;
if (footnote_count == 1 && inline_footnote_count > 0)
warning(1, (uint8_t*)"Both inline and regular footnotes present");
- else if (footnote_count > 1)
+ else if (!footnotes)
{
- REALLOC(footnotes, KeyValue, footnote_count * sizeof(KeyValue))
+ CALLOC(footnotes, KeyValue, footnote_count)
+ pfootnotes = footnotes;
+ }
+ else
+ {
+ REALLOCARRAY(footnotes, KeyValue, footnote_count)
pfootnotes = footnotes + footnote_count - 1;
}
CALLOC(pfootnotes->key, uint8_t, KEYSIZE)
@@ -2012,15 +2022,6 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
if (!buffer)
exit(error(1, (uint8_t*)"Empty buffer"));
- if (!vars)
- exit(error(EINVAL, (uint8_t*)"Invalid argument (vars)"));
-
- if (!links)
- exit(error(EINVAL, (uint8_t*)"Invalid argument (links)"));
-
- if (!macros)
- exit(error(EINVAL, (uint8_t*)"Invalid argument (macros)"));
-
title = get_value(vars, vars_count, (uint8_t*)"title", NULL);
title_heading_level = get_value(vars, vars_count,
(uint8_t*)"title-heading-level", NULL);
@@ -2168,7 +2169,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
vars_count++;
- if (vars_count > 1)
+ if (!vars)
+ {
+ CALLOC(vars, KeyValue, vars_count)
+ pvars = vars;
+ }
+ else
{
REALLOCARRAY(vars, KeyValue, vars_count)
pvars = vars + vars_count - 1;
@@ -2628,6 +2634,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
skip_eol = TRUE;
if (read_yaml_macros_and_links)
{
+ if (!macros)
+ {
+ macros_count = 1;
+ CALLOC(macros, KeyValue, macros_count)
+ pmacros = macros;
+ }
if (pmacros->value)
{
size_t value_len = u8_strlen(pmacros->value);
@@ -3118,7 +3130,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
if (!read_yaml_macros_and_links)
{
paralinks_count++;
- if (paralinks_count > 1)
+ if (!paralinks)
+ {
+ CALLOC(paralinks, KeyValue, paralinks_count)
+ pparalinks = paralinks;
+ }
+ else
{
REALLOCARRAY(paralinks, KeyValue, paralinks_count)
pparalinks = paralinks + paralinks_count - 1;
@@ -3218,7 +3235,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
{
uint8_t* url = get_value(links, links_count, token, NULL);
paralinks_count++;
- if (paralinks_count > 1)
+ if (!paralinks)
+ {
+ CALLOC(paralinks, KeyValue, paralinks_count)
+ pparalinks = paralinks;
+ }
+ else
{
REALLOCARRAY(paralinks, KeyValue, paralinks_count)
pparalinks = paralinks + paralinks_count - 1;
@@ -3254,7 +3276,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
{
uint8_t* url = get_value(links, links_count, token, NULL);
paralinks_count++;
- if (paralinks_count > 1)
+ if (!paralinks)
+ {
+ CALLOC(paralinks, KeyValue, paralinks_count)
+ pparalinks = paralinks;
+ }
+ else
{
REALLOCARRAY(paralinks, KeyValue, paralinks_count)
pparalinks = paralinks + paralinks_count - 1;
@@ -3290,7 +3317,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
case ':':
links_count++;
- if (links_count > 1)
+ if (!links)
+ {
+ CALLOC(links, KeyValue, links_count)
+ plinks = links;
+ }
+ else
{
REALLOCARRAY(links, KeyValue, links_count)
plinks = links + links_count - 1;
@@ -3583,6 +3615,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
&& (state & ST_YAML_VAL))
{
*ptoken = 0;
+ if (!vars)
+ {
+ vars_count = 1;
+ CALLOC(vars, KeyValue, vars_count)
+ pvars = vars;
+ }
pvars->value_size = u8_strlen(token)+1;
CALLOC(pvars->value, uint8_t, pvars->value_size)
u8_strncpy(pvars->value, token, pvars->value_size-1);
@@ -3614,6 +3652,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
skip_eol = TRUE;
if (read_yaml_macros_and_links)
{
+ if (!macros)
+ {
+ macros_count = 1;
+ CALLOC(macros, KeyValue, macros_count)
+ pmacros = macros;
+ }
if (pmacros->value)
{
size_t value_len = u8_strlen(pmacros->value);
@@ -3643,6 +3687,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
skip_eol = TRUE;
if (read_yaml_macros_and_links)
{
+ if (!footnotes)
+ {
+ footnote_count = 1;
+ CALLOC(footnotes, KeyValue, footnote_count)
+ pfootnotes = footnotes;
+ }
if (pfootnotes->value)
{
size_t value_len = u8_strlen(pfootnotes->value);
@@ -3671,6 +3721,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
{
if (read_yaml_macros_and_links)
{
+ if (!links)
+ {
+ links_count = 1;
+ CALLOC(links, KeyValue, links_count)
+ plinks = links;
+ }
plinks->value_size = u8_strlen(token)+1;
CALLOC(plinks->value, uint8_t, plinks->value_size)
u8_strncpy(plinks->value, token, plinks->value_size-1);
@@ -3743,6 +3799,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
skip_eol = TRUE;
if (read_yaml_macros_and_links)
{
+ if (!footnotes)
+ {
+ footnote_count = 1;
+ CALLOC(footnotes, KeyValue, footnote_count)
+ pfootnotes = footnotes;
+ }
if (pfootnotes->value)
{
size_t value_len = u8_strlen(pfootnotes->value);
@@ -3855,6 +3917,34 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL read_yaml_macros_and_links)
}
int
+slweb_cleanup()
+{
+ free(basedir);
+ free(input_dirname);
+ while (inline_footnote_count--)
+ free(inline_footnotes[inline_footnote_count]);
+ if (inline_footnotes)
+ free(inline_footnotes);
+ free_keyvalue(&footnotes, footnote_count);
+ free_keyvalue(¶links, paralinks_count);
+ free_keyvalue(&links, links_count);
+ free_keyvalue(¯os, macros_count);
+ free_keyvalue(&vars, vars_count);
+ if (footnotes)
+ free(footnotes);
+ if (paralinks)
+ free(paralinks);
+ if (links)
+ free(links);
+ if (macros)
+ free(macros);
+ if (vars)
+ free(vars);
+
+ return 0;
+}
+
+int
main(int argc, char** argv)
{
char* arg;
@@ -3991,33 +4081,18 @@ main(int argc, char** argv)
free(bufline);
}
- CALLOC(vars, KeyValue, 1)
- vars->key = NULL;
- vars->value = NULL;
- vars->value_size = 0;
-
- CALLOC(macros, KeyValue, 1)
- macros->key = NULL;
- macros->value = NULL;
- macros->value_size = 0;
-
- CALLOC(links, KeyValue, 1)
- links->key = NULL;
- links->value = NULL;
- links->value_size = 0;
-
- CALLOC(paralinks, KeyValue, 1)
- paralinks->key = NULL;
- paralinks->value = NULL;
- paralinks->value_size = 0;
-
- CALLOC(footnotes, KeyValue, 1)
- footnotes->key = NULL;
- footnotes->value = NULL;
- footnotes->value_size = 0;
-
- CALLOC(inline_footnotes, uint8_t*, 1)
- *inline_footnotes = NULL;
+ vars = NULL;
+ vars_count = 0;
+ macros = NULL;
+ macros_count = 0;
+ links = NULL;
+ links_count = 0;
+ paralinks = NULL;
+ paralinks_count = 0;
+ footnotes = NULL;
+ footnote_count = 0;
+
+ inline_footnotes = NULL;
inline_footnote_count = 0;
/* First pass: read YAML, macros and links */
@@ -4025,6 +4100,7 @@ main(int argc, char** argv)
if (result)
{
+ slweb_cleanup();
free(buffer);
return result;
}
@@ -4036,22 +4112,7 @@ main(int argc, char** argv)
/* Second pass: parse and output */
result = slweb_parse(buffer, output, FALSE);
- if (basedir)
- free(basedir);
- if (input_dirname)
- free(input_dirname);
- if (inline_footnotes)
- free(inline_footnotes);
- free_keyvalue(&footnotes, footnote_count);
- free_keyvalue(¶links, paralinks_count);
- free_keyvalue(&links, links_count);
- free_keyvalue(¯os, macros_count);
- free_keyvalue(&vars, vars_count);
- free(footnotes);
- free(paralinks);
- free(links);
- free(macros);
- free(vars);
+ slweb_cleanup();
free(buffer);
return result;