Skip to content

Commit 1ea0b38

Browse files
natoscottclaude
andcommitted
libpcp_import: address coderabbit review findings
pmiPutAtomValueHandle: validate atom is non-NULL before passing to _pmi_stuff_atomvalue, returning PM_ERR_ARG to avoid a segfault on PM_TYPE_STRING metrics where atom->cp would be dereferenced. archive.c _pmi_do_desc: when a descriptor for this PMID already exists in the archive, verify it is compatible before skipping the write. A package upgrade may have corrected an incorrect type, semantics, instance domain or units for a metric, in which case the old archive cannot be extended with new data. Return PM_ERR_LOGCHANGETYPE, PM_ERR_LOGCHANGESEM, PM_ERR_LOGCHANGEINDOM or PM_ERR_LOGCHANGEUNITS as appropriate so the caller has a precise diagnosis. qa/group: add local group to qa/1670 so the standard local sweep picks up the new append-mode coverage. Signed-off-by: Nathan Scott <nathans@redhat.com> Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 4dc7e96 commit 1ea0b38

3 files changed

Lines changed: 43 additions & 3 deletions

File tree

man/man3/pmistart.3

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,22 @@ If the archive files do not yet exist,
146146
.B PMI_APPEND
147147
behaves identically to creating a new archive (no flags).
148148
.PP
149+
.B PMI_APPEND
150+
and
151+
.B PMI_INHERIT
152+
may be used together.
153+
The inherited metric and instance-domain definitions are carried into
154+
the new context, and when the archive is opened on the first
155+
.BR pmiWrite (3)
156+
call, each inherited descriptor is checked against what is already
157+
on disk: compatible descriptors are silently skipped (no duplicate
158+
written); incompatible ones are rejected with an appropriate error
159+
(e.g.
160+
.BR PM_ERR_LOGCHANGETYPE ).
161+
When the previous context was writing to the same archive, every
162+
inherited descriptor already exists on disk so the combination is
163+
effectively a no-op beyond convenience.
164+
.PP
149165
If
150166
.I flags
151167
is zero, or neither

src/libpcp_import/src/archive.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,22 @@ check_metric(pmi_context *current, pmID pmid, int *needti)
195195
/*
196196
* If the archive was opened for appending, __pmLogLoadMeta() will
197197
* have populated hashpmid with all descriptors already on disk.
198-
* Skip re-writing a descriptor that is already there — metric
199-
* descriptors are immutable, so there is no need for duplicates
200-
* that would cause .meta to grow on every short-lived invocation.
198+
* Skip re-writing a descriptor that is already there, but first
199+
* verify it is compatible with the registered metric — e.g. a
200+
* package upgrade may have corrected a metric's type, semantics,
201+
* instance domain or units, in which case the old archive cannot
202+
* be extended with the new data.
201203
*/
202204
if (__pmLogLookupDesc(acp, pmid, &existing) == 0) {
205+
if (existing.type != current->metric[m].desc.type)
206+
return PM_ERR_LOGCHANGETYPE;
207+
if (existing.sem != current->metric[m].desc.sem)
208+
return PM_ERR_LOGCHANGESEM;
209+
if (existing.indom != current->metric[m].desc.indom)
210+
return PM_ERR_LOGCHANGEINDOM;
211+
if (memcmp(&existing.units, &current->metric[m].desc.units,
212+
sizeof(existing.units)) != 0)
213+
return PM_ERR_LOGCHANGEUNITS;
203214
current->metric[m].meta_done = 1;
204215
}
205216
else {

src/libpcp_import/src/import.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,17 @@ pmiStart(const char *archive, int flags)
351351
memset((void *)&current->logctl, 0, sizeof(current->logctl));
352352
memset((void *)&current->archctl, 0, sizeof(current->archctl));
353353
__pmLogWriterInit(&current->archctl, &current->logctl);
354+
/*
355+
* PMI_APPEND and PMI_INHERIT may be used together: the inherited
356+
* metric and indom definitions are carried into the new context, and
357+
* when the append archive is opened on the first pmiWrite() call,
358+
* each inherited descriptor is checked against what is already on
359+
* disk. Compatible descriptors are silently skipped (no duplicate
360+
* written); incompatible ones are rejected with PM_ERR_LOGCHANGE*.
361+
* In the common case -- inheriting from a context that was writing
362+
* to the same archive -- every inherited descriptor already exists
363+
* and the combination is effectively a no-op beyond convenience.
364+
*/
354365
if ((flags & PMI_INHERIT) && old_current != NULL) {
355366
current->nmetric = old_current->nmetric;
356367
if (old_current->metric != NULL) {
@@ -895,6 +906,8 @@ pmiPutAtomValueHandle(int handle, pmAtomValue *atom)
895906
return PM_ERR_NOCONTEXT;
896907
if (handle <= 0 || handle > current->nhandle)
897908
return current->last_sts = PMI_ERR_BADHANDLE;
909+
if (atom == NULL)
910+
return current->last_sts = PM_ERR_ARG;
898911

899912
return current->last_sts = _pmi_stuff_atomvalue(current, &current->handle[handle-1], atom);
900913
}

0 commit comments

Comments
 (0)