The names array is terminated by a NULL entry, thus allocate space for
one more than entries.
Fixes: #844
==6708==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000045b8 at pc 0x000000589ee1 bp 0x7ffcd1dee220 sp 0x7ffcd1dee218
READ of size 8 at 0x6060000045b8 thread T0
#0 0x589ee0 in String_freeArray ./XUtils.c:157:23
#1 0x56c9af in Settings_delete ./Settings.c:31:7
#2 0x4ee44b in CommandLine_run ./CommandLine.c:395:4
#3 0x4d6fb2 in main ./htop.c:15:11
#4 0x7ff3b8154e49 in __libc_start_main csu/../csu/libc-start.c:314:16
#5 0x428aa9 in _start (./htop+0x428aa9)
0x6060000045b8 is located 0 bytes to the right of 56-byte region [0x606000004580,0x6060000045b8)
allocated by thread T0 here:
#0 0x4a53f2 in __interceptor_calloc (./htop+0x4a53f2)
#1 0x5890ba in xCalloc ./XUtils.c:55:17
#2 0x50a044 in Header_writeBackToSettings ./Header.c:148:34
#3 0x4de861 in Action_runSetup ./Action.c:91:7
#4 0x4de861 in actionSetup ./Action.c:386:4
#5 0x515caf in MainPanel_eventHandler ./MainPanel.c:106:19
#6 0x56a5c1 in ScreenManager_run ./ScreenManager.c:235:19
#7 0x4ee13b in CommandLine_run ./CommandLine.c:364:4
#8 0x4d6fb2 in main ./htop.c:15:11
#9 0x7ff3b8154e49 in __libc_start_main csu/../csu/libc-start.c:314:16
Extending to right neighbors is intended for text meters with an
overlong content, so the whole text is shown if possible.
Multi column meters, like the combined memory and swap meter, position
its text depending on the given total width; keep the position to the
original assigned header slot.
Short term resolution for #796
It can happen that pcp-htop is presented multiple definitions
of the same dynamic meter, e.g. if /etc/pcp/htop/meters has a
definition matching one in ~/.config/htop/meters - instead of
exiting with a duplicate metric error provide more meaningful
diagnostics (on close) and also just skip over such entries.
System files override home directories which overrides those
found below the current working directory.
Also fix the derived metric error diagnostic; because this is
using CRT_fatalError, which is like perror(3), we must give a
meaningful prefix (like program name) at the string end.
This commit is based on exploratory work by Sohaib Mohamed.
The end goal is two-fold - to support addition of Meters we
build via configuration files for both the PCP platform and
for scripts ( https://github.com/htop-dev/htop/issues/526 )
Here, we focus on generic code and the PCP support. A new
class DynamicMeter is introduced - it uses the special case
'param' field handling that previously was used only by the
CPUMeter, such that every runtime-configured Meter is given
a unique identifier. Unlike with the CPUMeter this is used
internally only. When reading/writing to htoprc instead of
CPU(N) - where N is an integer param (CPU number) - we use
the string name for each meter. For example, if we have a
configuration for a DynamicMeter for some Redis metrics, we
might read and write "Dynamic(redis)". This identifier is
subsequently matched (back) up to the configuration file so
we're able to re-create arbitrary user configurations.
The PCP platform configuration file format is fairly simple.
We expand configs from several directories, including the
users homedir alongside htoprc (below htop/meters/) and also
/etc/pcp/htop/meters. The format will be described via a
new pcp-htop(5) man page, but its basically ini-style and
each Meter has one or more metric expressions associated, as
well as specifications for labels, color and so on via a dot
separated notation for individual metrics within the Meter.
A few initial sample configuration files are provided below
./pcp/meters that give the general idea. The PCP "derived"
metric specification - see pmRegisterDerived(3) - is used
as the syntax for specifying metrics in PCP DynamicMeters.
PR htop-dev/htop#70 got rid of the infrastructure for generating header
files, but it left behind some code duplication.
Some of cases are things that belong in the header file and don't need
to be repeated in the C file. Other cases are things that belong in the
C file and don't need to be in the header file.
In this commit I tried to fix all of these that I could find. When given
a choice I preferred keeping things out of the header file, unless they
were being used by someone else.
The MIN, MAX, CLAMP, MINIMUM, and MAXIMUM macros appear
throughout the codebase with many re-definitions. Make
a single copy of each in a common header file, and use
the BSD variants of MINIMUM/MAXIMUM due to conflicts in
the system <sys/param.h> headers.
Reasoning:
- implementation was unsound -- broke down when I added a fairly
basic macro definition expanding to a struct initializer in a *.c
file.
- made it way too easy (e.g. via otherwise totally innocuous git
commands) to end up with timestamps such that it always ran
MakeHeader.py but never used its output, leading to overbuild noise
when running what should be a null 'make'.
- but mostly: it's just an awkward way of dealing with C code.
Enough memory is allocated.
Header.c: In function ‘Header_readMeterName’:
Header.c:157:4: error: ‘strncpy’ specified bound depends on the length of the source argument [-Werror=stringop-overflow=]
157 | strncpy(name, Meter_name(meter), nameLen);
| ^
Header.c:154:18: note: length computed here
154 | int nameLen = strlen(Meter_name(meter));
| ^
The (this_) token was not expanded properly, but the bug was not caught
because all uses of this macro specifies (this_)=this .
Also parenthesize macro tokens to prevent further problems.
* size_t nmemb (number of elements) first, then size_t size
* do not assume char is size 1 but use sizeof()
* allocate for char, not pointer to char (found by Michael McConville,
fixes#261)