From b8bfdc0ec0e30046af809d75054850577d626ab9 Mon Sep 17 00:00:00 2001 From: Simon Rose Date: Fri, 23 Feb 2024 14:56:24 +0100 Subject: [PATCH] Fix segmentation fault when trying to save invalid long strings This can occur if you have something like the following: ``` record(waveform, "foo") { field(FTVL, "CHAR") field(NELM, "10") info(autosaveFields, "VAL VAL$") } ``` The `VAL$` field will cause a segmentation fault when it tries to save it to disk. The reason this seems to happen is that on one hand, `VAL$` is regarded by autosave as a valid field (it is a field, but with a `$` at the end). On the other hand, when connecting a monitor, the connection fails as the `VAL` field is not of the correcct type as defined in `dbChannelCreate` from EPICS base. This means that autosave will try to save the date from an unconnected array, with uninitialised pArray, causing a segmentation fault. --- asApp/src/dbrestore.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/asApp/src/dbrestore.c b/asApp/src/dbrestore.c index 2e73822..494cc48 100644 --- a/asApp/src/dbrestore.c +++ b/asApp/src/dbrestore.c @@ -1523,6 +1523,7 @@ void makeAutosaveFileFromDbInfo(char *fileBaseName, char *info_name) char *fname, *falloc=NULL, field[MAX_FIELD_SIZE], realfield[MAX_FIELD_SIZE]; FILE *out_fd; int searchRecord, flen; + int long_string = 0; if (!pdbbase) { errlogPrintf("autosave:makeAutosaveFileFromDbInfo: No Database Loaded\n"); @@ -1574,9 +1575,23 @@ void makeAutosaveFileFromDbInfo(char *fileBaseName, char *info_name) memcpy(field, pbegin, flen); field[flen]='\0'; strNcpy(realfield, field, MAX_FIELD_SIZE-1); - if (realfield[strlen(realfield)-1] == '$') realfield[strlen(realfield)-1] = '\0'; + if (realfield[strlen(realfield)-1] == '$') { + realfield[strlen(realfield)-1] = '\0'; + long_string = 1; + } - if (dbFindField(pdbentry, realfield) == 0) { + /* + * To be clear: This checks that /if/ something is a long + * string, then we have to match it against a valid field + * type; see dbChannelCreate in dbChannel.c from EPICS + * base. + */ + if ((dbFindField(pdbentry, realfield) == 0) && + (!long_string || + (pdbentry->pflddes->field_type == DBF_STRING || + (pdbentry->pflddes->field_type >= DBF_INLINK && + pdbentry->pflddes->field_type <= DBF_FWDLINK)))) + { fprintf(out_fd, "%s.%s\n", dbGetRecordName(pdbentry), field); } else { printf("makeAutosaveFileFromDbInfo: %s.%s not found\n", dbGetRecordName(pdbentry), field);