Skip to content

Commit

Permalink
Fix segmentation fault when trying to save invalid long strings
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
simon-ess committed Feb 23, 2024
1 parent 606903e commit b248355
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions asApp/src/dbrestore.c
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,7 @@ void makeAutosaveFileFromDbInfo(char *fileBaseName, char *info_name)
const char *info_value, *pbegin, *pend;
char *fname, *falloc=NULL, field[MAX_FIELD_SIZE], realfield[MAX_FIELD_SIZE];
FILE *out_fd;
int searchRecord, flen;
int searchRecord, flen, long_string;

if (!pdbbase) {
errlogPrintf("autosave:makeAutosaveFileFromDbInfo: No Database Loaded\n");
Expand Down Expand Up @@ -1574,9 +1574,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);
Expand Down

0 comments on commit b248355

Please sign in to comment.