[bug #68585] [pic, tbl] code not "ASAN_OPTIONS=alloc_dealloc_mismatch=1" clean
"G. Branden Robinson" <[email protected]> Fri, 31 Jul 2026 15:53:16 -0400 (EDT)
| Newsgroups | gmane.comp.printing.groff.bugs |
|---|---|
| Message-ID | <[email protected]> |
--8323329-1714636915-1785527596=:2042551
Content-Type: TEXT/plain; CHARSET=utf-8
Content-Transfer-Encoding: QUOTED-PRINTABLE
Content-Disposition: inline
URL:=0A <https://savannah.gnu.org/bugs/?68585>=0A=0A Summa=
ry: [pic,tbl] code not=0A"ASAN_OPTIONS=3Dalloc_dealloc_mismatch=3D1" clean=
=0A Group: GNU roff=0A Submitter: gbranden=
=0A Submitted: Fri 31 Jul 2026 07:53:12 PM UTC=0A =
Category: Preprocessor - others/general=0A Severity: 3 -=
Normal=0A Item Group: Incorrect behaviour=0A =
Status: Confirmed=0A Privacy: Public=0A Assign=
ed to: None=0A Open/Closed: Open=0A Discussion Lock: Un=
locked=0A Planned Release: None=0A=0A=0A _______________________=
________________________________=0A=0AFollow-up Comments:=0A=0A=0A---------=
----------------------------------------------=0ADate: Fri 31 Jul 2026 07:5=
3:12 PM UTC By: G. Branden Robinson <gbranden>=0ABruno reported [https://li=
sts.gnu.org/archive/html/groff/2026-07/msg00055.html=0Athese] [https://list=
s.gnu.org/archive/html/groff/2026-07/msg00057.html issues]=0Ato the _groff_=
list.=0A=0A=0AI tried building the groff-1.25.0.rc1 with clang's ASAN.=0AT=
he next error (during "make -k check"):=0A=0A GROFF doc/groff-man-pages=
.pdf=0A=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=3D=3D850834=3D=3D=
ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator=0A=0Ade=
lete []) on 0x7051a6beb4e0=0A #0 0x590f7622b86d in operator delete[](voi=
d*) =0A/home/runner/work/llvm-project/llvm-project/compiler-rt/lib/asan/asa=
n_new_delete.cpp:179:46=0A #1 0x590f7624cdff in block_entry::~block_entr=
y() =0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/tbl/table.cpp:=
667:3=0A #2 0x590f76282a24 in left_block_entry::~left_block_entry() =0A/=
build/groff-1.25.0.rc1/build-64-clang/../src/preproc/tbl/table.cpp:334:7=0A=
#3 0x590f76282a74 in left_block_entry::~left_block_entry() =0A/build/gr=
off-1.25.0.rc1/build-64-clang/../src/preproc/tbl/table.cpp:334:7=0A #4 0=
x590f7625ce86 in table::~table() =0A/build/groff-1.25.0.rc1/build-64-clang/=
../src/preproc/tbl/table.cpp:1309:5=0A #5 0x590f7622e9fc in process_tabl=
e(table_input&) =0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/tb=
l/main.cpp:1667:5=0A #6 0x590f7622dda7 in process_input_file(_IO_FILE*) =
=0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/tbl/main.cpp:270:4=
=0A #7 0x590f76243bee in main =0A/build/groff-1.25.0.rc1/build-64-clang/=
../src/preproc/tbl/main.cpp:1782:5=0A #8 0x73f1a782a600 in __libc_start_=
call_main =0Acsu/../sysdeps/nptl/libc_start_call_main.h:59:16=0A #9 0x73=
f1a782a717 in __libc_start_main csu/../csu/libc-start.c:360:3=0A #10 0x5=
90f76142984 in _start =0A(/build/groff-1.25.0.rc1/build-64-clang/tbl+0x5e98=
4)=0A=0A0x7051a6beb4e0 is located 0 bytes inside of 62-byte region =0A[0x70=
51a6beb4e0,0x7051a6beb51e)=0Aallocated by thread T0 here:=0A #0 0x590f76=
1e7f39 in calloc =0A/home/runner/work/llvm-project/llvm-project/compiler-rt=
/lib/asan/asan_malloc_linux.cpp:74:3=0A #1 0x590f7628be7a in string::ext=
ract() const =0A/build/groff-1.25.0.rc1/build-64-clang/../src/libs/libgroff=
/string.cpp:384:33=0A #2 0x590f76263398 in table::add_entry(int, int, st=
ring const&,=0Aentry_format =0Aconst*, char const*, int) =0A/build/groff-1.=
25.0.rc1/build-64-clang/../src/preproc/tbl/table.cpp:1545:17=0A #3 0x590=
f76240b46 in process_data(table_input&, format*, options*) =0A/build/groff-=
1.25.0.rc1/build-64-clang/../src/preproc/tbl/main.cpp:1567:13=0A #4 0x59=
0f7622e972 in process_table(table_input&) =0A/build/groff-1.25.0.rc1/build-=
64-clang/../src/preproc/tbl/main.cpp:1665:17=0A #5 0x590f7622dda7 in pro=
cess_input_file(_IO_FILE*) =0A/build/groff-1.25.0.rc1/build-64-clang/../src=
/preproc/tbl/main.cpp:270:4=0A #6 0x590f76243bee in main =0A/build/groff=
-1.25.0.rc1/build-64-clang/../src/preproc/tbl/main.cpp:1782:5=0A #7 0x73=
f1a782a600 in __libc_start_call_main =0Acsu/../sysdeps/nptl/libc_start_call=
_main.h:59:16=0A #8 0x73f1a782a717 in __libc_start_main csu/../csu/libc-=
start.c:360:3=0A #9 0x590f76142984 in _start =0A(/build/groff-1.25.0.rc1=
/build-64-clang/tbl+0x5e984)=0A=0ASUMMARY: AddressSanitizer: alloc-dealloc-=
mismatch =0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/tbl/table=
.cpp:667:3 in =0Ablock_entry::~block_entry()=0A=3D=3D850834=3D=3DHINT: if y=
ou don't care about these errors you may set =0AASAN_OPTIONS=3Dalloc_deallo=
c_mismatch=3D0=0A=3D=3D850834=3D=3DABORTING=0A/build/groff-1.25.0.rc1/build=
-64-clang/groff: error: tbl: Aborted=0A=0AExplanation:=0Acalloc() pairs wit=
h free().=0Anew[] pairs with delete[].=0A=0ABruno=0A=0A=0A=0AI tried buildi=
ng the groff-1.25.0.rc1 with clang's ASAN.=0AThe next error (during "make -=
k check"):=0A=0A GROFF contrib/mom/examples/slide-demo.pdf=0A=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=3D=3D851776=3D=3DERROR: AddressSani=
tizer: alloc-dealloc-mismatch (malloc vs operator=0A=0Adelete []) on 0x6d23=
571e0330=0A #0 0x587f8b4ae9ed in operator delete[](void*) =0A/home/runne=
r/work/llvm-project/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:1=
79:46=0A #1 0x587f8b4f8b0f in output::~output() =0A/build/groff-1.25.0.r=
c1/build-64-clang/../src/preproc/pic/object.cpp:47:3=0A #2 0x587f8b5345a=
4 in common_output::~common_output() =0A/build/groff-1.25.0.rc1/build-64-cl=
ang/../src/preproc/pic/common.h:20:7=0A #3 0x587f8b53c614 in simple_outp=
ut::~simple_output() =0A/build/groff-1.25.0.rc1/build-64-clang/../src/prepr=
oc/pic/troff.cpp:37:7=0A #4 0x587f8b53757a in troff_output::~troff_outpu=
t() =0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/pic/troff.cpp:=
276:1=0A #5 0x587f8b5375d4 in troff_output::~troff_output() =0A/build/gr=
off-1.25.0.rc1/build-64-clang/../src/preproc/pic/troff.cpp:274:1=0A #6 0=
x587f8b4f8423 in main =0A/build/groff-1.25.0.rc1/build-64-clang/../src/prep=
roc/pic/main.cpp:698:3=0A #7 0x710357e2a600 in __libc_start_call_main =
=0Acsu/../sysdeps/nptl/libc_start_call_main.h:59:16=0A #8 0x710357e2a717=
in __libc_start_main csu/../csu/libc-start.c:360:3=0A #9 0x587f8b3c5b04=
in _start =0A(/build/groff-1.25.0.rc1/build-64-clang/pic+0x80b04)=0A=0A0x6=
d23571e0330 is located 0 bytes inside of 7-byte region =0A[0x6d23571e0330,0=
x6d23571e0337)=0Aallocated by thread T0 here:=0A #0 0x587f8b46aee4 in ma=
lloc =0A/home/runner/work/llvm-project/llvm-project/compiler-rt/lib/asan/as=
an_malloc_linux.cpp:67:3=0A #1 0x587f8b54c677 in strsave(char const*) =
=0A/build/groff-1.25.0.rc1/build-64-clang/../src/libs/libgroff/strsave.cpp:=
36:33=0A #2 0x587f8b4f8d41 in output::set_args(char const*) =0A/build/gr=
off-1.25.0.rc1/build-64-clang/../src/preproc/pic/object.cpp:62:12=0A #3 =
0x587f8b4f7356 in do_picture(_IO_FILE*) =0A/build/groff-1.25.0.rc1/build-64=
-clang/../src/preproc/pic/main.cpp:297:10=0A #4 0x587f8b4f5f4f in do_fil=
e(char const*) =0A/build/groff-1.25.0.rc1/build-64-clang/../src/preproc/pic=
/main.cpp:395:2=0A #5 0x587f8b4f8241 in main =0A/build/groff-1.25.0.rc1/=
build-64-clang/../src/preproc/pic/main.cpp:691:7=0A #6 0x710357e2a600 in=
__libc_start_call_main =0Acsu/../sysdeps/nptl/libc_start_call_main.h:59:16=
=0A #7 0x710357e2a717 in __libc_start_main csu/../csu/libc-start.c:360:3=
=0A #8 0x587f8b3c5b04 in _start =0A(/build/groff-1.25.0.rc1/build-64-cla=
ng/pic+0x80b04)=0A=0ASUMMARY: AddressSanitizer: alloc-dealloc-mismatch =0A/=
build/groff-1.25.0.rc1/build-64-clang/../src/preproc/pic/object.cpp:47:3 in=
=0Aoutput::~output()=0A=3D=3D851776=3D=3DHINT: if you don't care about the=
se errors you may set =0AASAN_OPTIONS=3Dalloc_dealloc_mismatch=3D0=0A=3D=3D=
851776=3D=3DABORTING=0A/build/groff-1.25.0.rc1/build-64-clang/groff: error:=
pic: Aborted=0A=0AExplanation:=0Amalloc() pairs with free().=0Anew[] pairs=
with delete[].=0A=0ABruno=0A=0A=0AHowever, trying to resolve the _tbl_ iss=
ue pulled on a long thread of=0A`const`-incorrectness and an insufficiently=
well documented internal API for=0A_libgroff_'s "string" class.=0A=0AWhile=
eventually we can likely switch to C++ STL strings for everything=0Aoutsid=
e the formatter itself (_troff_), because we're handling character=0Asequen=
ces in a Unixy-way in those places, we'll need to retain the string=0Aclass=
--perhaps renamed "membuf" or something, because "characters" take on new=
=0Ameaning inside the formatter, and more importantly, we must deal with=0A=
sequences that have internal null bytes. In a diversion, for example, a nu=
ll=0Abyte in its "macro_header"'s "char_list" indicates the presence of a=
=0Acorresponding "node" in the "node_list".=0A=0Ahttps://cgit.git.savannah.=
gnu.org/cgit/groff.git/tree/src/roff/troff/input.cpp?h=3D1.25.0.rc1#n4068=
=0A=0AThe=0A[https://www.gnu.org/software/groff/manual/groff.html.node/GNU-=
troff-Internals.html#GNU-troff-Internals=0A"GNU troff Internals" section of=
groff's Texinfo manual also throws a little=0Alight on these matters].=0A=
=0AHere's a sketch of my current plan of attack:=0A=0A* Kill off straggling=
uses of malloc()/calloc()/realloc()/free() in=0A_src/libs/libgroff/string.=
cpp_.=0A* string::contents() should return a `const char *`.=0A* string::ex=
tract() should return a `char *`.=0A* Neither function should worry about i=
nternal nulls; they should return a=0A`char` sequence up to the first null =
byte. The return type will imply as much=0Ato any experienced C/C++ progra=
mmer anyway.=0A* Users of the `string` class that employ _either_ `contents=
()` or `extract()`=0Acan be flagged as potential migrants to the C++ standa=
rd `string` class.=0A=0AHere's a diff of how far I pulled the yarn before g=
iving up on trying to solve=0Athis problem for _groff_ 1.25.=0A=0A=0Adiff -=
-git a/src/devices/grops/ps.cpp b/src/devices/grops/ps.cpp=0Aindex d4aa564c=
8..8950f36db 100644=0A--- a/src/devices/grops/ps.cpp=0A+++ b/src/devices/gr=
ops/ps.cpp=0A@@ -906,7 +906,7 @@ void ps_printer::define_encoding(const cha=
r *encoding,=0A int i;=0A for (i =3D 0; i < 256; i++)=0A vec[i] =3D=
0;=0A- char *path;=0A+ const char *path;=0A if (strchr(encoding, '/') =
!=3D 0 /* nullptr */)=0A fatal("a '/' is not allowed in encoding file n=
ame: '%1'", encoding);=0A FILE *fp =3D font::open_file(encoding, &path);=
=0A@@ -942,7 +942,7 @@ void ps_printer::define_encoding(const char *encodin=
g,=0A }=0A lineno++;=0A }=0A- free(path);=0A+ free(const_cast<c=
har *>(path));=0A out.put_literal_symbol(make_encoding_name(encoding_inde=
x))=0A .put_delimiter('[');=0A for (i =3D 0; i < 256; i++) {=0Adiff =
--git a/src/devices/grops/psrm.cpp b/src/devices/grops/psrm.cpp=0Aindex 6cc=
67ca36..106188f83 100644=0A--- a/src/devices/grops/psrm.cpp=0A+++ b/src/dev=
ices/grops/psrm.cpp=0A@@ -114,7 +114,7 @@ struct resource {=0A unsigned f=
lags;=0A string version;=0A unsigned revision;=0A- char *filename;=0A+=
const char *filename;=0A int rank;=0A resource(resource_type, string =
&, string & =3D an_empty_string, unsigned =3D=0A0);=0A ~resource();=0A@@ =
-130,13 +130,13 @@ resource::resource(resource_type t, string &n, string=0A=
&v, unsigned r)=0A if (type =3D=3D RESOURCE_FILE) {=0A if (name.searc=
h('\0') >=3D 0)=0A error("file name contains character code 0");=0A- =
filename =3D name.extract();=0A+ filename =3D name.contents();=0A }=
=0A }=0A =0A resource::~resource()=0A {=0A- free(filename);=0A+ free(cons=
t_cast<char *>(filename));=0A }=0A =0A void resource::print_type_and_name(F=
ILE *outfp)=0A@@ -323,7 +323,7 @@ void resource_manager::output_prolog(ps_o=
utput &out)=0A {=0A FILE *outfp =3D out.get_file();=0A out.end_line();=
=0A- char *path;=0A+ const char *path;=0A if (getenv("GROPS_PROLOGUE") =
=3D=3D 0 /* nullptr */) {=0A if (setenv("GROPS_PROLOGUE", GROPS_PROLOGU=
E, 1 /* overwrite */)=0A !=3D 0)=0A@@ -342,7 +342,7 @@ void resource=
_manager::output_prolog(ps_output &out)=0A putc('\n', outfp);=0A proces=
s_file(-1, fp, path, outfp);=0A fclose(fp);=0A- free(path);=0A+ free(co=
nst_cast<char *>(path));=0A fputs("%%EndResource\n", outfp);=0A }=0A =0A@=
@ -366,7 +366,7 @@ void resource_manager::supply_resource(resource *r, int=
=0Arank,=0A r->flags |=3D resource::BUSY;=0A if (rank > r->rank)=0A =
r->rank =3D rank;=0A- char *path =3D 0 /* nullptr */;=0A+ const char *pa=
th =3D 0 /* nullptr */;=0A FILE *fp =3D 0 /* nullptr */;=0A if (r->file=
name !=3D 0 /* nullptr */) {=0A if (r->type =3D=3D RESOURCE_FONT) {=0A@=
@ -406,7 +406,7 @@ void resource_manager::supply_resource(resource *r, int=
=0Arank,=0A process_file(rank, fp, path, outfp);=0A fclose(fp);=0A =
if (r->type =3D=3D RESOURCE_FONT)=0A- free(path);=0A+ free(co=
nst_cast<char *>(path));=0A if (outfp) {=0A if (r->type =3D=3D RE=
SOURCE_FILE && is_document)=0A fputs("%%EndDocument\n", outfp);=0A@@=
-1098,7 +1098,7 @@ void resource_manager::process_file(int rank, FILE *fp,=
=0A =0A void resource_manager::read_download_file()=0A {=0A- char *path =
=3D 0 /* nullptr */;=0A+ const char *path =3D 0 /* nullptr */;=0A FILE *=
fp =3D font::open_file("download", &path);=0A if (0 /* nullptr */ =3D=3D =
fp)=0A fatal("cannot open 'download' file: %1", strerror(errno));=0A@@ =
-1115,7 +1115,7 @@ void resource_manager::read_download_file()=0A =
" font '%1'", p);=0A lookup_font(p)->filename =3D =
strsave(q);=0A }=0A- free(path);=0A+ free(const_cast<char *>(path));=0A=
fclose(fp);=0A }=0A =0Adiff --git a/src/include/font.h b/src/include/fon=
t.h=0Aindex 85bae6719..39dd33c4b 100644=0A--- a/src/include/font.h=0A+++ b/=
src/include/font.h=0A@@ -218,7 +218,7 @@ public:=0A static void command_l=
ine_font_dir(const char *); // Prepend given=0A =
// path (arg1) to the list of directories in which=0A =
// to look up fonts.=0A- static FILE *open_file(const char *, char **); =
// Open a font=0A+ static FILE *open_file(const char *, const char **); //=
Open a font=0A // description file with the given n=
ame (arg1),=0A // searching along the current font p=
ath, and=0A // rejecting `arg1` if it contains a sla=
sh (see=0A@@ -228,10 +228,10 @@ public:=0A // opened=
file's stream pointer. If not found,=0A // arg2 is=
unchanged, and a null pointer is=0A // returned.=0A=
- static FILE *open_resource_file(const char *, char **); // Open an=0A- =
// externally supplied (non-groff) file required=0A- =
// by the output driver, possibly to embed=0A- =
// content in the generated file. Like=0A+ static FILE *op=
en_resource_file(const char *, const char **); // Open=0A+ =
// an externally supplied (non-groff) file=0A+ =
// required by the output driver, possibly to=0A+ // =
embed content in the generated file. Like=0A // `op=
en_file()` except that it accepts slashes=0A // in `=
arg1`. Examples include Type 1 fonts=0A // embedded=
in PostScript output.=0Adiff --git a/src/include/searchpath.h b/src/includ=
e/searchpath.h=0Aindex 65b94e8a0..af7c28298 100644=0A--- a/src/include/sear=
chpath.h=0A+++ b/src/include/searchpath.h=0A@@ -25,8 +25,9 @@ public:=0A =
int add_home, int add_current);=0A ~search_path();=0A void c=
ommand_line_dir(const char *);=0A- FILE *open_file(const char *, char **);=
=0A- FILE *open_file_cautiously(const char *, char ** =3D 0 /* nullptr */,=
=0A+ FILE *open_file(const char *, const char **);=0A+ FILE *open_file_ca=
utiously(const char *,=0A+ const char ** =3D 0 /=
* nullptr */,=0A const char * =3D 0 /* nullptr =
*/);=0A };=0A =0Adiff --git a/src/include/stringclass.h b/src/include/strin=
gclass.h=0Aindex 131c13718..f3736ddba 100644=0A--- a/src/include/stringclas=
s.h=0A+++ b/src/include/stringclass.h=0A@@ -76,7 +76,7 @@ public:=0A int =
search(const char) const;=0A bool contains(const char) const;=0A ssize_=
t find(const char *) const;=0A- char *extract() const;=0A+ const char *ex=
tract() const;=0A size_t json_length() const;=0A const char *json_extra=
ct() const;=0A void json_dump() const;=0Adiff --git a/src/libs/libgroff/f=
ont.cpp b/src/libs/libgroff/font.cpp=0Aindex 362abf527..b6c1886e7 100644=0A=
--- a/src/libs/libgroff/font.cpp=0A+++ b/src/libs/libgroff/font.cpp=0A@@ -7=
9,13 +79,13 @@ struct font_widths_cache {=0A =0A struct text_file {=0A FI=
LE *fp;=0A- char *path;=0A+ const char *path;=0A int lineno;=0A int l=
inebufsize;=0A bool recognize_comments;=0A bool silent;=0A char *buf;=
=0A- text_file(FILE *fp, char *p);=0A+ text_file(FILE *fp, const char *p)=
;=0A ~text_file();=0A bool next_line();=0A void error(const char *for=
mat,=0A@@ -98,8 +98,8 @@ struct text_file {=0A const errarg &ar=
g3 =3D empty_errarg);=0A };=0A =0A-text_file::text_file(FILE *p, char *s) :=
fp(p), path(s), lineno(0),=0A- linebufsize(128), recognize_comments(true)=
, silent(false),=0A+text_file::text_file(FILE *p, const char *s) : fp(p), p=
ath(s),=0A+ lineno(0), linebufsize(128), recognize_comments(true), silent(=
false),=0A buf(0 /* nullptr */)=0A {=0A }=0A@@ -107,7 +107,7 @@ text_file=
::text_file(FILE *p, char *s) : fp(p), path(s),=0Alineno(0),=0A text_file::=
~text_file()=0A {=0A delete[] buf;=0A- free(path);=0A+ free(const_cast<=
char *>(path));=0A if (fp)=0A fclose(fp);=0A }=0A@@ -898,7 +898,7 @@ =
again:=0A =0A bool font::load(bool want_diagnostic, bool validate_only)=0A =
{=0A- char *path;=0A+ const char *path;=0A FILE *fp =3D open_file(filen=
ame, &path);=0A if (0 /* nullptr */ =3D=3D fp) {=0A if (want_diagnost=
ic)=0A@@ -1284,7 +1284,7 @@ static struct numeric_directive {=0A const char=
*font::load_desc()=0A {=0A int nfonts =3D 0;=0A- char *path;=0A+ const=
char *path;=0A FILE *fp =3D open_file("DESC", &path);=0A if (0 /* null=
ptr */ =3D=3D fp)=0A return 0 /* nullptr */;=0Adiff --git a/src/libs/li=
bgroff/fontfile.cpp b/src/libs/libgroff/fontfile.cpp=0Aindex 148fd3be3..133=
66eae6 100644=0A--- a/src/libs/libgroff/fontfile.cpp=0A+++ b/src/libs/libgr=
off/fontfile.cpp=0A@@ -64,7 +64,7 @@ void font::command_line_font_dir(const=
char *dir)=0A font_path.command_line_dir(dir);=0A }=0A =0A-FILE *font::o=
pen_file(const char *nm, char **pathp)=0A+FILE *font::open_file(const char =
*nm, const char **pathp)=0A {=0A assert(nm !=3D 0 /* nullptr */);=0A as=
sert(device !=3D 0 /* nullptr */);=0A@@ -85,7 +85,7 @@ FILE *font::open_fil=
e(const char *nm, char **pathp)=0A return fp;=0A }=0A =0A-FILE *font::ope=
n_resource_file(const char *nm, char **pathp)=0A+FILE *font::open_resource_=
file(const char *nm, const char **pathp)=0A {=0A assert(nm !=3D 0 /* null=
ptr */);=0A assert(device !=3D 0 /* nullptr */);=0Adiff --git a/src/libs/=
libgroff/searchpath.cpp=0Ab/src/libs/libgroff/searchpath.cpp=0Aindex 3ad25a=
704..4ed59b0d5 100644=0A--- a/src/libs/libgroff/searchpath.cpp=0A+++ b/src/=
libs/libgroff/searchpath.cpp=0A@@ -113,7 +113,7 @@ void search_path::comman=
d_line_dir(const char *s)=0A delete[] old;=0A }=0A =0A-FILE *search_path:=
:open_file(const char *name, char **pathp)=0A+FILE *search_path::open_file(=
const char *name, const char **pathp)=0A {=0A assert(name !=3D 0 /* nullp=
tr */);=0A if (IS_ABSOLUTE(name) || *dirs =3D=3D '\0') {=0A@@ -174,7 +174=
,8 @@ FILE *search_path::open_file(const char *name, char=0A**pathp)=0A r=
eturn 0 /* nullptr */;=0A }=0A =0A-FILE *search_path::open_file_cautiously(=
const char *name, char **pathp,=0A+FILE *search_path::open_file_cautiously(=
const char *name,=0A+ const char **pa=
thp,=0A const char *mode)=0A {=0A =
if (0 /* nullptr */ =3D=3D mode)=0Adiff --git a/src/libs/libgroff/string.cp=
p b/src/libs/libgroff/string.cpp=0Aindex eb01c3078..0fb810dbd 100644=0A--- =
a/src/libs/libgroff/string.cpp=0A+++ b/src/libs/libgroff/string.cpp=0A@@ -3=
72,7 +372,7 @@ ssize_t string::find(const char *c) const=0A // Return point=
er to null-terminated C string; any nulls internal to the=0A // string are =
omitted. The caller is responsible for `free()`ing the=0A // returned stor=
age.=0A-char *string::extract() const=0A+const char *string::extract() cons=
t=0A {=0A char *p =3D ptr;=0A size_t n =3D len;=0A@@ -381,15 +381,18 @@=
char *string::extract() const=0A for (i =3D 0; i < n; i++)=0A if (p[=
i] =3D=3D '\0')=0A nnuls++;=0A- char *q =3D static_cast<char *>(call=
oc(n + 1 - nnuls, sizeof(char)));=0A+ size_t extracted_length =3D n + 1 /*=
'\0' */ - nnuls;=0A+ //char *q =3D static_cast<char *>(calloc(n + 1 - nnu=
ls, sizeof(char)));=0A+ string *q =3D new string;=0A+ //(void) memset(q, =
0, extracted_length);=0A if (q !=3D 0 /* nullptr */) {=0A- char *r =3D=
q;=0A+ q->set_length(extracted_length);=0A for (i =3D 0; i < n; i++=
)=0A if (p[i] !=3D '\0')=0A- *r++ =3D p[i];=0A- *r =3D '\0';=
=0A+ *q++ =3D p[i];=0A+ *q =3D '\0';=0A }=0A- return q;=0A+ re=
turn q->contents();=0A }=0A =0A // Compute length of JSON representation of=
object.=0Adiff --git a/src/preproc/eqn/main.cpp b/src/preproc/eqn/main.cpp=
=0Aindex 2574f7d37..a9ac291a5 100644=0A--- a/src/preproc/eqn/main.cpp=0A+++=
b/src/preproc/eqn/main.cpp=0A@@ -467,13 +467,13 @@ int main(int argc, char=
**argv)=0A " 'groff -Thtml -e')\n", device);=0A }=0A if (wan=
t_startup_file) {=0A- char *path;=0A+ const char *path;=0A FILE *=
fp =3D config_macro_path.open_file(STARTUP_FILE, &path);=0A if (fp !=3D=
0 /* nullptr */) {=0A do_file(fp, path);=0A if (fclose(fp) < 0=
)=0A fatal("cannot close '%1': %2", STARTUP_FILE, strerror(errno));=
=0A- free(path);=0A+ free(const_cast<char *>(path));=0A }=0A =
else=0A error("cannot open startup file '%1': %2", STARTUP_FILE,=
=0Adiff --git a/src/preproc/grn/main.cpp b/src/preproc/grn/main.cpp=0Aindex=
dc2835f0e..773c611dd 100644=0A--- a/src/preproc/grn/main.cpp=0A+++ b/src/p=
reproc/grn/main.cpp=0A@@ -577,7 +577,7 @@ conv(FILE *fp,=0A error(=
"no picture file name at line %1", baseline);=0A return;=0A }=
=0A- char *path;=0A+ const char *path;=0A gfp =3D macro_pat=
h.open_file(gremlinfile, &path);=0A if (0 /* nullptr */ =3D=3D gfp) {=
=0A error("cannot open picture file '%1': %2", gremlinfile,=0A@@ -58=
6,7 +586,7 @@ conv(FILE *fp,=0A }=0A PICTURE =3D DBRead(gfp); =
/* read picture file */=0A fclose(gfp);=0A- free(path);=0A+ =
free(const_cast<char *>(path));=0A if (DBNullelt(PICTURE))=0A =
return; /* If a request is made to make the */=0A =
/* picture fit into a specific area, */=0Adiff --g=
it a/src/preproc/html/pre-html.cpp b/src/preproc/html/pre-html.cpp=0Aindex =
7b6993db2..e9c87c52d 100644=0A--- a/src/preproc/html/pre-html.cpp=0A+++ b/s=
rc/preproc/html/pre-html.cpp=0A@@ -330,7 +330,7 @@ static bool get_line(FIL=
E *f, const char *file_name, int=0Alineno)=0A =0A static unsigned int get_r=
esolution(void)=0A {=0A- char *pathp;=0A+ const char *pathp;=0A FILE *f=
;=0A unsigned int res =3D 0;=0A f =3D font_path.open_file(devps_desc, &=
pathp);=0A@@ -347,7 +347,7 @@ static unsigned int get_resolution(void)=0A =
break;=0A }=0A }=0A- free(pathp);=0A+ free(const_cast<char *>=
(pathp));=0A fclose(f);=0A return res;=0A }=0A@@ -360,7 +360,7 @@ stati=
c unsigned int get_resolution(void)=0A =0A static char *get_image_generator=
(void)=0A {=0A- char *pathp;=0A+ const char *pathp;=0A FILE *f;=0A ch=
ar *generator =3D 0 /* nullptr */;=0A const char keyword[] =3D "image_gen=
erator";=0A@@ -393,7 +393,7 @@ static char *get_image_generator(void)=0A =
break;=0A }=0A }=0A- free(pathp);=0A+ free(const_cast<char *>(=
pathp));=0A fclose(f);=0A return generator;=0A }=0Adiff --git a/src/pre=
proc/preconv/preconv.cpp=0Ab/src/preproc/preconv/preconv.cpp=0Aindex cd13b5=
070..fdd74de9d 100644=0A--- a/src/preproc/preconv/preconv.cpp=0A+++ b/src/p=
reproc/preconv/preconv.cpp=0A@@ -885,14 +885,18 @@ get_tag_lines(FILE *fp, =
string &data)=0A data +=3D char(c);=0A }=0A }=0A- return data=
.extract();=0A+ // We need a mutable string.=0A+ const char *tag_lines_co=
nst =3D data.extract();=0A+ char *tag_lines =3D strdup(tag_lines_const); /=
/ XXX: leaky=0A+ free(const_cast<char *>(tag_lines_const));=0A+ return ta=
g_lines;=0A }=0A =0A // ---------------------------------------------------=
------=0A // Indicate whether C string starts with a comment.=0A // -------=
--------------------------------------------------=0A static bool=0A-is_com=
ment_line(char *s)=0A+is_comment_line(const char *s)=0A {=0A if (!s || !*=
s)=0A return false;=0A@@ -1128,17 +1132,17 @@ do_file(const char *filen=
ame)=0A fp =3D fopen(filename, FOPEN_RB);=0A reported_filename =3D =
"'" + string(filename) + "'";=0A }=0A- char *c_reported_filename =3D rep=
orted_filename.extract();=0A+ const char *c_reported_filename =3D reported=
_filename.extract();=0A if (!fp) {=0A error("cannot open %1: %2", c_r=
eported_filename, strerror(errno));=0A- free(c_reported_filename);=0A+ =
free(const_cast<char *>(c_reported_filename));=0A return false;=0A =
}=0A if (is_debugging) {=0A fprintf(stderr, "processing %s\n", c_repo=
rted_filename);=0A fflush(stderr);=0A }=0A- free(c_reported_filename=
);=0A+ free(const_cast<char *>(c_reported_filename));=0A if (fseek(fp, 0=
L, SEEK_SET) =3D=3D 0)=0A is_seekable =3D true;=0A else {=0Adiff --gi=
t a/src/preproc/soelim/soelim.cpp b/src/preproc/soelim/soelim.cpp=0Aindex 1=
064edaef..68a61bb3f 100644=0A--- a/src/preproc/soelim/soelim.cpp=0A+++ b/sr=
c/preproc/soelim/soelim.cpp=0A@@ -194,7 +194,7 @@ static void do_so(const c=
har *line)=0A =0A static bool do_file(const char *filename)=0A {=0A- char =
*file_name_in_path =3D 0 /* nullptr */;=0A+ const char *file_name_in_path =
=3D 0 /* nullptr */;=0A FILE *fp =3D include_search_path.open_file_cautio=
usly(filename,=0A &file_name_in_path);=0A int err =3D errno;=0A@@ -=
202,7 +202,7 @@ static bool do_file(const char *filename)=0A if (strcmp(f=
ilename, "-") && file_name_in_path !=3D 0 /* nullptr */)=0A whole_filen=
ame =3D file_name_in_path;=0A whole_filename +=3D '\0';=0A- free(file_na=
me_in_path);=0A+ free(const_cast<char *>(file_name_in_path));=0A if (0 /=
* nullptr */ =3D=3D fp) {=0A error("cannot open '%1': %2", whole_filena=
me.contents(),=0A strerror(err));=0Adiff --git a/src/preproc/tbl/t=
able.cpp b/src/preproc/tbl/table.cpp=0Aindex bd0abcda6..6b085bf77 100644=0A=
--- a/src/preproc/tbl/table.cpp=0A+++ b/src/preproc/tbl/table.cpp=0A@@ -154=
3,7 +1543,9 @@ void table::add_entry(int r, int c, const string &str,=0A =
allocate(r);=0A table_entry *e =3D 0 /* nullptr */;=0A ssize_t len =3D =
str.length();=0A- char *s =3D str.extract();=0A+ const char *s_const =3D =
str.extract();=0A+ // We need a mutable string.=0A+ char *s =3D strdup(s_=
const); // XXX: leaky=0A // Diagnose escape sequences that can wreak havo=
c in generated output.=0A if (len > 1) {=0A // A comment on a control=
line or in a text block is okay.=0A@@ -1648,7 +1650,9 @@ void table::add_e=
ntry(int r, int c, const string &str,=0A e =3D new empty_entry(this, =
f);=0A }=0A else {=0A- char *glyph =3D str.substring(2, len - =
2).extract();=0A+ const char *glyph_const =3D str.substring(2, len - 2=
).extract();=0A+ // We need a mutable string.=0A+ char *glyph =3D=
strdup(glyph_const); // XXX: leaky=0A e =3D new repeated_char_entry(=
this, f, glyph);=0A }=0A }=0Adiff --git a/src/roff/troff/env.cpp b/sr=
c/roff/troff/env.cpp=0Aindex 8f4542d89..a71ed55ea 100644=0A--- a/src/roff/t=
roff/env.cpp=0A+++ b/src/roff/troff/env.cpp=0A@@ -4454,7 +4454,7 @@ void hy=
phen_trie::interpret_patterns_file(const char=0A*name,=0A buf[i] =3D 0;=
=0A int num[WORD_MAX + 1];=0A errno =3D 0;=0A- char *path =3D 0;=0A+ =
const char *path =3D 0;=0A FILE *fp =3D mac_path->open_file(name, &path);=
=0A if (0 /* nullptr */ =3D=3D fp) {=0A error("cannot open hyphenatio=
n pattern file '%1': %2", name,=0A@@ -4582,7 +4582,7 @@ void hyphen_trie::i=
nterpret_patterns_file(const char=0A*name,=0A }=0A }=0A fclose(fp);=
=0A- free(path);=0A+ free(const_cast<char *>(path));=0A return;=0A }=0A=
=0Adiff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp=0Ainde=
x c9e6be2ac..8b6ae00e3 100644=0A--- a/src/roff/troff/input.cpp=0A+++ b/src/=
roff/troff/input.cpp=0A@@ -9831,7 +9831,7 @@ static void parse_output_page_=
list(const char *p)=0A }=0A }=0A =0A-static FILE *open_macro_package(cons=
t char *mac, char **path)=0A+static FILE *open_macro_package(const char *ma=
c, const char **path)=0A {=0A // Try `mac`.tmac first, then tmac.`mac`. =
Expect ENOENT errors.=0A // ISO C++ does not permit VLAs on the stack.=0A=
@@ -9863,13 +9863,13 @@ static FILE *open_macro_package(const char *mac, ch=
ar=0A**path)=0A =0A static void process_macro_package_argument(const char *=
mac)=0A {=0A- char *path;=0A+ const char *path;=0A FILE *fp =3D open_ma=
cro_package(mac, &path);=0A if (0 /* nullptr */ =3D=3D fp)=0A fatal("=
cannot open macro file named in '-m' command-line argument"=0A " '=
%1': %2", mac, strerror(errno));=0A const char *s =3D symbol(path).conten=
ts();=0A- free(path);=0A+ free(const_cast<char *>(path));=0A input_stac=
k::push(new file_iterator(fp, s));=0A tok.next();=0A process_input_stac=
k();=0A@@ -9877,13 +9877,13 @@ static void process_macro_package_argument(c=
onst char=0A*mac)=0A =0A static void process_startup_file(const char *filen=
ame)=0A {=0A- char *path;=0A+ const char *path;=0A search_path *orig_ma=
c_path =3D mac_path;=0A mac_path =3D &config_macro_path;=0A FILE *fp =
=3D mac_path->open_file(filename, &path);=0A if (fp !=3D 0 /* nullptr */)=
{=0A input_stack::push(new file_iterator(fp, symbol(path).contents()))=
;=0A- free(path);=0A+ free(const_cast<char *>(path));=0A tok.next=
();=0A process_input_stack();=0A }=0A@@ -9896,11 +9896,11 @@ static v=
oid process_startup_file(const char=0A*filename)=0A static void do_macro_so=
urce(bool quietly)=0A {=0A char *macro_filename =3D read_rest_of_line_as_=
argument();=0A- char *path;=0A+ const char *path;=0A FILE *fp =3D mac_p=
ath->open_file(macro_filename, &path);=0A if (fp !=3D 0 /* nullptr */) {=
=0A input_stack::push(new file_iterator(fp, macro_filename));=0A- fr=
ee(path);=0A+ free(const_cast<char *>(path));=0A }=0A else=0A //=
Suppress diagnostic only if we're operating quietly and it's an=0A=0A=0A=
=0A=0A=0A=0A=0A=0A=0A=0A _______________________________________________=
________=0A=0AReply to this item at:=0A=0A <https://savannah.gnu.org/bugs/=
?68585>=0A=0A_______________________________________________=0AMessage sent=
via Savannah=0Ahttps://savannah.gnu.org/=0A
--8323329-1714636915-1785527596=:2042551
Content-Type: APPLICATION/pgp-signature; name=signature.asc
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQQk97aszIMMAvLLwm6qLAuaBUf3TgUCamz9LAAKCRCqLAuaBUf3
Tt3+AP0bE1fxOjXNb5lhbxYY5HJV5YMcKzK8+CyRyKQNs/kmjAD/eKU4gtyp/Fl+
lERZFPRaKRjtG7r+rx13mtUMJI0CRQk=
=xTnh
-----END PGP SIGNATURE-----
--8323329-1714636915-1785527596=:2042551--