From 514d836a07e95ad662f9243ed37ae4c19d00596b Mon Sep 17 00:00:00 2001 From: Andrew C Aitchison Date: Tue, 9 Jun 2026 13:35:26 +0100 Subject: [PATCH 1/3] Update tools/MT-Unsafe.py to find all the unsafe functions listed in man elf_flagelf Also update addons/threadsafety.py to include these functions. This man page lists several unsafe functions on one line. --- addons/threadsafety.py | 5 +++++ tools/MT-Unsafe.py | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/addons/threadsafety.py b/addons/threadsafety.py index 390a245d4e1..7414f0ac553 100755 --- a/addons/threadsafety.py +++ b/addons/threadsafety.py @@ -112,7 +112,12 @@ 'drand48', 'ecvt', 'elf_fill', + 'elf_flagdata', + 'elf_flagehdr', 'elf_flagelf', + 'elf_flagphdr', + 'elf_flagscn', + 'elf_flagshdr', 'encrypt', 'endfsent', 'endgrent', diff --git a/tools/MT-Unsafe.py b/tools/MT-Unsafe.py index 965a6261db8..b3cb3c35e72 100755 --- a/tools/MT-Unsafe.py +++ b/tools/MT-Unsafe.py @@ -85,17 +85,26 @@ def man_search(manpage): apis = set() for lineread in MANPAGE: lineread = str(lineread) - dprint(2, '%s' % (lineread)) + dprint(1, '%s' % (lineread)) if 'MT-Safe' in lineread: vprint(1, 'clearing MT-Safe %s', lineread) apis.clear() - res = re.search(r'\.BR\s+(\w+)\s', lineread) - # vprint(1, '%s for %s' % (res, lineread)) - if res: - apis.add(res.group(1)) - dprint(1, 'found api %s in %s' % (res.group(1), lineread)) - continue + if '.BR' in lineread: + function_names = re.sub(r'^.*\.BR ', '', lineread) + dprint(1, 'function_names 1:\n\t%s\n' % (function_names)) + function_names = re.sub(r'\\\\~', '', function_names) + dprint(1, 'function_names 1a:\n\t%s\n' % (function_names)) + function_names = function_names.replace(r'\n', '') + dprint(1, 'function_names 2:\n\t%s\n' % (function_names)) + function_names = re.sub(r"[~() ']+", '', function_names) + dprint(1, 'function_names 3:\n\t%s\n' % (function_names)) + function_names = re.split(',', function_names) + dprint(1, 'function_names split:\n\t%s\n' % (function_names)) + + for fn in function_names: + if fn: + apis.add(fn) if 'MT-Unsafe' in lineread: resUnsafe = re.search("MT-Unsafe\\s+(.*)(\\n\'|$)", lineread) @@ -103,7 +112,7 @@ def man_search(manpage): if resUnsafe: values = resUnsafe.group(1) dprint(1, 'a %s' % values) - values = re.sub(r'\\n\'$', '', values) + values = re.sub(r"\\n\'$", '', values) # values = values.split(' ') dprint(1, 'values %s' % list(values)) From 0d5c4a8c28a85fa6d33a463763dc36f2827e8ff3 Mon Sep 17 00:00:00 2001 From: Andrew C Aitchison Date: Wed, 10 Jun 2026 16:11:34 +0100 Subject: [PATCH 2/3] whitespace suggested by pylint --- tools/MT-Unsafe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/MT-Unsafe.py b/tools/MT-Unsafe.py index b3cb3c35e72..c97e5e47803 100755 --- a/tools/MT-Unsafe.py +++ b/tools/MT-Unsafe.py @@ -101,7 +101,7 @@ def man_search(manpage): dprint(1, 'function_names 3:\n\t%s\n' % (function_names)) function_names = re.split(',', function_names) dprint(1, 'function_names split:\n\t%s\n' % (function_names)) - + for fn in function_names: if fn: apis.add(fn) From c28bcf1510a5352b9f17eccad48ccf11fb01e536 Mon Sep 17 00:00:00 2001 From: Andrew C Aitchison Date: Sat, 29 Aug 2026 19:21:15 +0100 Subject: [PATCH 3/3] A man page for regression testing tools/MT-Unsafe.py Includes expected output. --- test/tools/MT-Unsafe.3 | 69 +++++++++++++++++++++++++++++++++ test/tools/MT-Unsafe.3.expected | 15 +++++++ tools/MT-Unsafe.py | 3 +- 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 test/tools/MT-Unsafe.3 create mode 100644 test/tools/MT-Unsafe.3.expected diff --git a/test/tools/MT-Unsafe.3 b/test/tools/MT-Unsafe.3 new file mode 100644 index 00000000000..991b276a242 --- /dev/null +++ b/test/tools/MT-Unsafe.3 @@ -0,0 +1,69 @@ +.TH MT-Unsafe 3 2026-06-21 "CppCheck" "CppCheck Developer Tools" +.SH NAME +MT-Unsafe.py + +.SH DESCRIPTION +This man page does +.BI not +document real functions +(although some of the functions it names +.I are +real). + +This man page is test data for the +.BI tools/MT-Unsafe.py +script, which is used to convert man pages into data for the +.B cppcheck +addon +.I threadsafety.py\fR. +The output should match +.I test/tools/MT-Unsafe.3.expected\fR. +E.g.: + +.I tools/MT-Unsafe.py test/tools/MT-Unsafe.3 | diff - test/tools/MT-Unsafe.3.expected +should produce no output. + +.\ .SH SEE ALSO + +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). + +.TS +allbox; +lbx lb lb +l l l. +Interface Attribute Value +T{ +.na +.nh +.BR elf_flagelf (),\~elf_flagehdr(),\~elf_flagphdr(),\~elf_flagscn(),\~elf_flagshdr(),\~elf_flagdata() +T} Thread safety MT-Unsafe +T{ +.na +.nh +.BR safe_function (),\~second_safe_function(),third_function() +T} Thread safety MT-Safe +T{ +.na +.nh +.BR race_function (), +.BR second_race_function () +T} Thread safety MT-Unsafe race:argument +.TE + + +.\ .SH STANDARDS + +.\ .SH HISTORY +.\ Original version Andrew C. Aitchison 2026-06-21 + +.SH AUTHORS +.PP +\fBAndrew Aitchison\fR <\&github@aitchison\&.me\&.uk\&> +.RS 4 +Wrote MT-Unsafe.py and this man page\&. +.RE +.SH COPYRIGHT +Copyright (C) 2026 Cppcheck team. +.\ .SH NOTES diff --git a/test/tools/MT-Unsafe.3.expected b/test/tools/MT-Unsafe.3.expected new file mode 100644 index 00000000000..ff23d616feb --- /dev/null +++ b/test/tools/MT-Unsafe.3.expected @@ -0,0 +1,15 @@ +{ + # Types marked MT-Unsafe + '', + 'race:argument', + # APIs marked MT-Unsafe + 'elf_flagdata', + 'elf_flagehdr', + 'elf_flagelf', + 'elf_flagphdr', + 'elf_flagscn', + 'elf_flagshdr', + 'race_function', + 'second_race_function', +} + diff --git a/tools/MT-Unsafe.py b/tools/MT-Unsafe.py index c97e5e47803..122d93fcf12 100755 --- a/tools/MT-Unsafe.py +++ b/tools/MT-Unsafe.py @@ -97,7 +97,7 @@ def man_search(manpage): dprint(1, 'function_names 1a:\n\t%s\n' % (function_names)) function_names = function_names.replace(r'\n', '') dprint(1, 'function_names 2:\n\t%s\n' % (function_names)) - function_names = re.sub(r"[~() ']+", '', function_names) + function_names = re.sub(r"[~() '\\\n]+", '', function_names) dprint(1, 'function_names 3:\n\t%s\n' % (function_names)) function_names = re.split(',', function_names) dprint(1, 'function_names split:\n\t%s\n' % (function_names)) @@ -105,6 +105,7 @@ def man_search(manpage): for fn in function_names: if fn: apis.add(fn) + dprint(1, 'added function "%s"' % fn) if 'MT-Unsafe' in lineread: resUnsafe = re.search("MT-Unsafe\\s+(.*)(\\n\'|$)", lineread)