gbranden pushed a commit to branch master
in repository groff.
commit e72d0504286aadb33ed641816c6cc4b7c63f5604
Author: G. Branden Robinson <[email protected]>
AuthorDate: Sun May 31 22:50:39 2026 -0500
[grohtml]: Wrap heap allocations with try/catch.
Be more fastidious with heap-allocated memory.
* src/devices/grohtml/post-html.cpp: Use ISO C++98 exceptions to handle
heap storage allocation failures. Preprocessor-include C++ "<new>"
header file.
(files::add_new_file)
(text_glob::text_glob_html)
(text_glob::text_glob_special)
(text_glob::text_glob_line)
(text_glob::text_glob_auto_image)
(text_glob::text_glob_tag)
(list:add)
(list:insert)
(page::page)
(page::add)
(page::add_tag)
(page::add_line)
(html_font::load_html_font)
(assert_state::add)
(generate_img_src)
(html_printer::write_header)
(html_printer::lookahead_for_tables)
(html_printer::flush_page)
(html_printer::draw)
(html_printer::html_printer)
(html_printer::begin_page)
(get_str)
(main): Declare and initialize variables outside of `try`/`catch`
blocks. Initialize such variables with null pointers where
appropriate.
Continues the long process of fixing Savannah #68192.
---
ChangeLog | 35 +++++
src/devices/grohtml/post-html.cpp | 278 +++++++++++++++++++++++++++++---------
2 files changed, 252 insertions(+), 61 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 98a042c5f..8ad741c7d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2026-06-04 G. Branden Robinson <[email protected]>
+
+ [grohtml]: Be more fastidious with heap-allocated memory.
+
+ * src/devices/grohtml/post-html.cpp: Use ISO C++98 exceptions to
+ handle heap storage allocation failures. Preprocessor-include
+ C++ "<new>" header file. Declare and initialize variables
+ outside of `try`/`catch` blocks. Initialize such variables with
+ null pointers where appropriate.
+ (files::add_new_file)
+ (text_glob::text_glob_html)
+ (text_glob::text_glob_special)
+ (text_glob::text_glob_line)
+ (text_glob::text_glob_auto_image)
+ (text_glob::text_glob_tag)
+ (list:add)
+ (list:insert)
+ (page::page)
+ (page::add)
+ (page::add_tag)
+ (page::add_line)
+ (html_font::load_html_font)
+ (assert_state::add)
+ (generate_img_src)
+ (html_printer::write_header)
+ (html_printer::lookahead_for_tables)
+ (html_printer::flush_page)
+ (html_printer::draw)
+ (html_printer::html_printer)
+ (html_printer::begin_page)
+ (get_str)
+ (main): Do it.
+
+ Continues the long process of fixing Savannah #68192.
+
2026-06-03 G. Branden Robinson <[email protected]>
* src/devices/grohtml/post-html.cpp: Fix memory leak.
diff --git a/src/devices/grohtml/post-html.cpp
b/src/devices/grohtml/post-html.cpp
index 6378d9b99..782ced836 100644
--- a/src/devices/grohtml/post-html.cpp
+++ b/src/devices/grohtml/post-html.cpp
@@ -39,6 +39,7 @@ along with this program. If not, see
<http://www.gnu.org/licenses/>. */
#include <getopt.h> // getopt_long()
+#include <new> // std::bad_alloc
#include <stack>
#include <vector>
@@ -267,11 +268,20 @@ void files::move_next (void)
void files::add_new_file (FILE *f)
{
assert(f != 0 /* nullptr */);
+ if (0 /* nullptr */ == f)
+ return;
+ file *new_file = 0 /* nullptr */;
+ try {
+ new_file = new file(f);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for file object");
+ }
if (0 /* nullptr */ == head) {
- head = new file(f);
+ head = new_file;
tail = head;
} else {
- tail->next = new file(f);
+ tail->next = new_file;
tail = tail->next;
}
ptr = tail;
@@ -589,11 +599,17 @@ void text_glob::text_glob_html (style *s, char *str, int
length,
int min_vertical , int min_horizontal,
int max_vertical , int max_horizontal)
{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, FALSE, 0 /* nullptr */);
- // TODO: penultimate argument above is not really a Boolean
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob(s, str, length,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal,
+ FALSE, FALSE, FALSE, FALSE, 0);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object"
+ " of length %1", length);
+ }
*this = *g;
delete g;
}
@@ -610,11 +626,17 @@ void text_glob::text_glob_special (style *s, char *str,
int length,
int min_vertical, int min_horizontal,
int max_vertical, int max_horizontal)
{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal,
- FALSE, FALSE, TRUE, FALSE, 0 /* nullptr */);
- // TODO: penultimate argument above is not really a Boolean
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob(s, str, length,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal,
+ FALSE, FALSE, TRUE, FALSE, 0);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for special text_glob object"
+ " of length %1", length);
+ }
*this = *g;
delete g;
}
@@ -628,11 +650,16 @@ void text_glob::text_glob_line (style *s,
int max_vertical, int max_horizontal,
int thickness_value)
{
- text_glob *g = new text_glob(s, "", 0,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal,
- FALSE, FALSE, FALSE, TRUE,
- thickness_value);
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob(s, "", 0,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal,
+ FALSE, FALSE, FALSE, TRUE, thickness_value);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for line text_glob object");
+ }
*this = *g;
delete g;
}
@@ -667,10 +694,17 @@ void text_glob::text_glob_auto_image(style *s, char *str,
int length,
int max_vertical,
int max_horizontal)
{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal,
- TRUE, TRUE, FALSE, FALSE, 0 /* nullptr */);
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob(s, str, length,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal,
+ TRUE, TRUE, FALSE, FALSE, 0);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for auto_image text_glob object"
+ " of length %1", length);
+ }
*this = *g;
delete g;
}
@@ -683,10 +717,17 @@ void text_glob::text_glob_tag (style *s, char *str, int
length,
int min_vertical, int min_horizontal,
int max_vertical, int max_horizontal)
{
- text_glob *g = new text_glob(s, str, length,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal,
- TRUE, FALSE, FALSE, FALSE, 0 /* nullptr */);
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob(s, str, length,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal,
+ TRUE, FALSE, FALSE, FALSE, 0);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for tag text_glob object"
+ " of length %1", length);
+ }
*this = *g;
delete g;
}
@@ -1144,9 +1185,15 @@ void list::add (text_glob *in, int line_number,
{
// create a new list element with datum and position fields
// initialized
- element_list *t = new element_list(in, line_number,
- min_vertical, min_horizontal,
- max_vertical, max_horizontal);
+ element_list *t = 0 /* nullptr */;
+ try {
+ t = new element_list(in, line_number,
+ min_vertical, min_horizontal,
+ max_vertical, max_horizontal);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for element_list object");
+ }
element_list *last;
#if 0
@@ -1330,9 +1377,15 @@ void list::insert (text_glob *in)
if (0 /* nullptr */ == ptr)
ptr = head;
- element_list *t = new element_list(in, ptr->lineno,
- ptr->minv, ptr->minh,
- ptr->maxv, ptr->maxh);
+ element_list *t = 0 /* nullptr */;
+ try {
+ t = new element_list(in, ptr->lineno,
+ ptr->minv, ptr->minh,
+ ptr->maxv, ptr->maxh);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for element_list object");
+ }
if (ptr == tail)
tail = t;
ptr->right->left = t;
@@ -1411,7 +1464,13 @@ page::page()
void page::insert_tag (const string &str)
{
if (str.length() > 0) {
- text_glob *g=new text_glob();
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob();
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object");
+ }
text_glob *f=glyphs.get_data();
g->text_glob_tag(&f->text_style, buffer.add_string(str),
str.length(), f->minv, f->minh, f->maxv, f->maxh);
@@ -1429,7 +1488,13 @@ void page::add (style *s, const string &str,
int max_vertical, int max_horizontal)
{
if (str.length() > 0) {
- text_glob *g=new text_glob();
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob();
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object");
+ }
g->text_glob_html(s, buffer.add_string(str), str.length(),
min_vertical, min_horizontal,
max_vertical, max_horizontal);
@@ -1448,20 +1513,23 @@ void page::add_tag (style *s, const string &str,
int max_vertical, int max_horizontal)
{
if (str.length() > 0) {
- text_glob *g;
-
- if (strncmp((str+'\0').contents(), "devtag:.auto-image",
- strlen("devtag:.auto-image")) == 0) {
+ text_glob *g = 0 /* nullptr */;
+ try {
g = new text_glob();
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object");
+ }
+ if (strncmp((str+'\0').contents(), "devtag:.auto-image",
+ strlen("devtag:.auto-image")) == 0)
g->text_glob_auto_image(s, buffer.add_string(str), str.length(),
min_vertical, min_horizontal,
max_vertical, max_horizontal);
- } else {
- g = new text_glob();
+ else
g->text_glob_tag(s, buffer.add_string(str), str.length(),
min_vertical, min_horizontal,
max_vertical, max_horizontal);
- }
+
glyphs.add(g, line_number, min_vertical, min_horizontal,
max_vertical, max_horizontal);
}
@@ -1477,7 +1545,13 @@ void page::add_line (style *s,
int thickness)
{
if (y_1 == y_2) {
- text_glob *g = new text_glob();
+ text_glob *g = 0 /* nullptr */;
+ try {
+ g = new text_glob();
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object");
+ }
g->text_glob_line(s,
min(y_1, y_2), min(x_1, x_2),
max(y_1, y_2), max(x_1, x_2),
@@ -1620,7 +1694,13 @@ public:
html_font *html_font::load_html_font(const char *s)
{
- html_font *f = new html_font(s);
+ html_font *f = 0 /* nullptr */;
+ try {
+ f = new html_font(s);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_font object");
+ }
if (!f->load()) {
delete f;
return 0 /* nullptr */;
@@ -1894,7 +1974,12 @@ void assert_state::add (assert_pos **h,
compare(t, v, f, l);
else {
if (0 /* nullptr */ == t) {
- t = new assert_pos;
+ try {
+ t = new assert_pos;
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for assert_pos object");
+ }
t->next = *h;
(*h) = t;
}
@@ -2596,7 +2681,13 @@ static int exists (const char *filename)
static string &generate_img_src (const char *filename)
{
assert(filename != 0 /* nullptr */);
- string *s = new string("");
+ string *s = 0 /* nullptr */;
+ try {
+ s = new string("");
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for string object");
+ }
while ((filename != 0 /* nullptr */) && (' ' == filename[0]))
filename++;
@@ -2760,7 +2851,7 @@ void html_printer::write_xhtml_anchor (text_glob *h)
void html_printer::write_header (void)
{
if (! header.header_buffer.empty()) {
- text_glob *a = 0;
+ text_glob *a = 0 /* nullptr */;
// TODO: boolify
int space = current_paragraph->retrieve_para_space() || seen_space;
@@ -2775,8 +2866,12 @@ void html_printer::write_header (void)
// now we save the header so we can issue a list of links
header.no_of_headings++;
style st;
-
- a = new text_glob();
+ try {
+ a = new text_glob();
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text_glob object");
+ }
a->text_glob_html(&st,
header.headings
.add_string(header.header_buffer.contents()),
@@ -3978,12 +4073,18 @@ void html_printer::lookahead_for_tables (void)
int ncol = 0;
int colmin = 0; // pacify compiler
int colmax = 0; // pacify compiler
- html_table *tbl = new html_table(&html, -1);
+ html_table *tbl = 0 /* nullptr */;
const char *tab_defs = 0 /* nullptr */;
char align = 'L';
int nf = FALSE;
int old_pageoffset = pageoffset;
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
remove_courier_tabs();
page_contents->dump_page();
insert_tab0_foreach_tab();
@@ -4026,7 +4127,12 @@ void html_printer::lookahead_for_tables (void)
page_contents->glyphs.move_left();
insert_tab_te();
start_of_table->remember_table(tbl);
- tbl = new html_table(&html, -1);
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
page_contents->insert_tag(string("*** TAB -> COL ***"));
if (tab_defs != 0 /* nullptr */)
tbl->tab_stops->init(tab_defs);
@@ -4054,7 +4160,12 @@ void html_printer::lookahead_for_tables (void)
page_contents->glyphs.move_left();
insert_tab_te();
start_of_table->remember_table(tbl);
- tbl = new html_table(&html, -1);
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
page_contents->insert_tag(string("*** COL -> TAB ***"));
start_of_table = 0 /* nullptr */;
last = 0 /* nullptr */;
@@ -4076,7 +4187,12 @@ void html_printer::lookahead_for_tables (void)
&& (start_of_table != 0 /* nullptr */)) {
add_table_end("*** CE ***");
start_of_table->remember_table(tbl);
- tbl = new html_table(&html, -1);
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
start_of_table = 0 /* nullptr */;
last = 0 /* nullptr */;
} else if (g->is_ta()) {
@@ -4087,7 +4203,12 @@ void html_printer::lookahead_for_tables (void)
if (start_of_table != 0 /* nullptr */) {
add_table_end("*** TABS ***");
start_of_table->remember_table(tbl);
- tbl = new html_table(&html, -1);
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
start_of_table = 0 /* nullptr */;
type_of_col = none_tag;
last = 0 /* nullptr */;
@@ -4106,7 +4227,12 @@ void html_printer::lookahead_for_tables (void)
add_table_end("*** CROSSED COLS ***");
start_of_table->remember_table(tbl);
- tbl = new html_table(&html, -1);
+ try {
+ tbl = new html_table(&html, -1);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for html_table object");
+ }
start_of_table = 0 /* nullptr */;
type_of_col = none_tag;
last = 0 /* nullptr */;
@@ -4182,7 +4308,12 @@ void html_printer::flush_page (void)
fprintf(stderr, "\n\n*** flushed page ***\n\n");
html.simple_comment("new page called");
#endif
- page_contents = new page;
+ try {
+ page_contents = new page;
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for page object");
+ }
}
/*
@@ -4641,7 +4772,12 @@ void html_printer::draw(int code, int *p, int np,
case 'F':
// fill with color env->fill
delete background;
- background = new color;
+ try {
+ background = new color;
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for color object");
+ }
*background = *env->fill;
break;
@@ -4718,8 +4854,12 @@ html_printer::html_printer()
linelength = font::res*13/2;
if (0 == paper_length)
paper_length = 11*font::res;
-
- page_contents = new page();
+ try {
+ page_contents = new page;
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for page object");
+ }
}
/*
@@ -5297,7 +5437,12 @@ void html_printer::begin_page(int n)
output_hpos = -1;
output_vpos = -1;
output_vpos_max = -1;
- current_paragraph = new html_text(&html, dialect);
+ try {
+ current_paragraph = new html_text(&html, dialect);
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for text object");
+ }
do_indent(get_troff_indent(), pageoffset, linelength);
current_paragraph->do_para("", FALSE);
}
@@ -5651,12 +5796,18 @@ static char *get_str (const char *s, char **n)
if ((0 /* nullptr */ == s) || (0 /* nullptr */ == n))
return 0 /* nullptr */;
int i = 0;
- char *v;
+ char *v = 0 /* nullptr */;
while ((s[i] != '\0') && (s[i] != ',') && (s[i] != ']'))
i++;
if (i>0) {
- v = new char[i+1];
+ size_t amount = i + 1;
+ try {
+ v = new char[amount];
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate %1 bytes for char array", amount);
+ }
memcpy(v, s, i+1);
v[i] = '\0';
if (',' == s[i])
@@ -5952,7 +6103,12 @@ int main(int argc, char **argv)
break;
case 'b':
// set background color to white
- default_background = new color;
+ try {
+ default_background = new color;
+ }
+ catch (const std::bad_alloc &exc) {
+ fatal("cannot allocate storage for color object");
+ }
default_background->set_gray(color::MAX_COLOR_VAL);
break;
case 'C':
_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit