From 5e1bad2b34fb2b3920d7dedb2d6abe239cc17f80 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 10 Jan 2019 14:45:18 -0600 Subject: [PATCH 1/3] dbStatic parser: Reject empty object names --- src/ioc/dbStatic/dbLexRoutines.c | 64 +++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/ioc/dbStatic/dbLexRoutines.c b/src/ioc/dbStatic/dbLexRoutines.c index b11f4a3fa..3df3c7f3a 100644 --- a/src/ioc/dbStatic/dbLexRoutines.c +++ b/src/ioc/dbStatic/dbLexRoutines.c @@ -428,6 +428,10 @@ static void dbMenuHead(char *name) dbMenu *pdbMenu; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbMenuHead: Menu name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->menuList); if(pgphentry) { duplicate = TRUE; @@ -441,6 +445,10 @@ static void dbMenuHead(char *name) static void dbMenuChoice(char *name,char *value) { + if (!*name) { + yyerror("dbMenuChoice: Menu choice name can't be empty"); + return; + } if(duplicate) return; allocTemp(epicsStrDup(name)); allocTemp(epicsStrDup(value)); @@ -488,6 +496,10 @@ static void dbRecordtypeHead(char *name) dbRecordType *pdbRecordType; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbRecordtypeHead: Recordtype name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->recordTypeList); if(pgphentry) { duplicate = TRUE; @@ -505,7 +517,11 @@ static void dbRecordtypeFieldHead(char *name,char *type) { dbFldDes *pdbFldDes; int i; - + + if (!*name) { + yyerrorAbort("dbRecordtypeFieldHead: Field name can't be empty"); + return; + } if(duplicate) return; pdbFldDes = dbCalloc(1,sizeof(dbFldDes)); allocTemp(pdbFldDes); @@ -572,7 +588,7 @@ static void dbRecordtypeFieldItem(char *name,char *value) if(sscanf(value,"%hd",&pdbFldDes->special)==1) { return; } - yyerror("Illegal special value."); + yyerror("Illegal 'special' value."); return; } if(strcmp(name,"pp")==0) { @@ -581,13 +597,13 @@ static void dbRecordtypeFieldItem(char *name,char *value) } else if((strcmp(value,"NO")==0) || (strcmp(value,"FALSE")==0)) { pdbFldDes->process_passive = FALSE; } else { - yyerror("Illegal value. Must be NO or YES"); + yyerror("Illegal 'pp' value, must be YES/NO/TRUE/FALSE"); } return; } if(strcmp(name,"interest")==0) { if(sscanf(value,"%hd",&pdbFldDes->interest)!=1) - yyerror("Illegal value. Must be integer"); + yyerror("Illegal 'interest' value, must be integer"); return; } if(strcmp(name,"base")==0) { @@ -596,13 +612,13 @@ static void dbRecordtypeFieldItem(char *name,char *value) } else if(strcmp(value,"HEX")==0) { pdbFldDes->base = CT_HEX; } else { - yyerror("Illegal value. Must be CT_DECIMAL or CT_HEX"); + yyerror("Illegal 'base' value, must be DECIMAL/HEX"); } return; } if(strcmp(name,"size")==0) { if(sscanf(value,"%hd",&pdbFldDes->size)!=1) - yyerror("Illegal value. Must be integer"); + yyerror("Illegal 'size' value, must be integer"); return; } if(strcmp(name,"extra")==0) { @@ -794,6 +810,10 @@ static void dbDriver(char *name) drvSup *pdrvSup; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbDriver: Driver name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList); if(pgphentry) { return; @@ -813,6 +833,10 @@ static void dbRegistrar(char *name) dbText *ptext; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbRegistrar: Registrar name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->registrarList); if(pgphentry) { return; @@ -832,6 +856,10 @@ static void dbFunction(char *name) dbText *ptext; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbFunction: Function name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->functionList); if(pgphentry) { return; @@ -851,6 +879,10 @@ static void dbVariable(char *name, char *type) dbVariableDef *pvar; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbVariable: Variable name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->variableList); if(pgphentry) { return; @@ -871,6 +903,10 @@ static void dbBreakHead(char *name) brkTable *pbrkTable; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbBreakHead: Breaktable name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->bptList); if(pgphentry) { duplicate = TRUE; @@ -973,6 +1009,10 @@ static void dbRecordHead(char *recordType, char *name, int visible) DBENTRY *pdbentry; long status; + if (!*name) { + yyerrorAbort("dbRecordHead: Record name can't be empty"); + return; + } badch = strpbrk(name, " \"'.$"); if (badch) { epicsPrintf("Bad character '%c' in record name \"%s\"\n", @@ -1072,6 +1112,10 @@ static void dbRecordInfo(char *name, char *value) tempListNode *ptempListNode; long status; + if (!*name) { + yyerrorAbort("dbRecordInfo: Info item name can't be empty"); + return; + } if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; @@ -1091,6 +1135,10 @@ static void dbRecordAlias(char *name) tempListNode *ptempListNode; long status; + if (!*name) { + yyerrorAbort("dbRecordAlias: Alias name can't be empty"); + return; + } if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; @@ -1108,6 +1156,10 @@ static void dbAlias(char *name, char *alias) DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; + if (!*alias) { + yyerrorAbort("dbAlias: Alias name can't be empty"); + return; + } dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n", From 9ef3b773486128f157bae6ff2931bf5ffcd44537 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 1 Feb 2019 16:14:45 -0600 Subject: [PATCH 2/3] Fix ca/client/perl/Makefile for macOS Mojave ... in which Apple moved the Perl headers into XCode. This should also make the build a little more forgiving on other architectures that have incomplete Perl installations; it gives up trying to build the Perl bindings with a warning if perl.h is missing. --- src/ca/client/perl/Makefile | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/ca/client/perl/Makefile b/src/ca/client/perl/Makefile index 9b61b3b32..98352b2e7 100644 --- a/src/ca/client/perl/Makefile +++ b/src/ca/client/perl/Makefile @@ -8,6 +8,18 @@ TOP=../../../.. include $(TOP)/configure/CONFIG +ifdef T_A + PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version) + PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname) + PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME) + + PERL_ARCHLIB := $(shell $(PERL) ../perlConfig.pl archlib) + PERL_h = $(PERL_ARCHLIB)/CORE/perl.h + + EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils + PERLBIN := $(shell $(PERL) ../perlConfig.pl bin) + XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp)) + # Special settings for Darwin: ifeq ($(OS_CLASS),Darwin) # Use hdepends command (not GNU compiler flags) @@ -18,22 +30,23 @@ ifeq ($(OS_CLASS),Darwin) # Perl loadable libraries on Darwin have funny names LOADABLE_SHRLIB_PREFIX = LOADABLE_SHRLIB_SUFFIX = .$(shell $(PERL) ../perlConfig.pl dlext) + +ifeq ($(wildcard $(PERL_h)),) + # Perl's headers moved in Mojave + SDK_PATH := $(shell xcodebuild -version -sdk macosx Path) + PERL_ARCHLIB := $(SDK_PATH)/$(PERL_ARCHLIB) +endif endif -ifdef T_A - PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version) - PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname) - PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME) - - EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils - PERLBIN := $(shell $(PERL) ../perlConfig.pl bin) - XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp)) - +ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) ifeq ($(strip $(XSUBPP)),) $(warning Perl's xsubpp program was not found.) $(warning The Perl CA module will not be built.) else -ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) +ifeq ($(wildcard $(PERL_h)),) + $(warning Perl's C header files were not found.) + $(warning The Perl CA module will not be built.) +else ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32 LOADABLE_LIBRARY_HOST = Cap5 @@ -52,10 +65,11 @@ endif endif endif endif +endif Cap5_SRCS = Cap5.xs Cap5_LIBS = ca Com -Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE +Cap5_INCLUDES = -I$(PERL_ARCHLIB)/CORE Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags) CLEANS += Cap5.c From 736075daf6507c847c7ea90b2cf21342fecc832e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 1 Feb 2019 16:49:11 -0600 Subject: [PATCH 3/3] Document macOS Mojave fix --- documentation/RELEASE_NOTES.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 4e317c84d..c47dc2d5b 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -16,6 +16,15 @@ +

Perl CA bindings fixed for macOS Mojave

+ +

Apple removed some Perl header files from macOS Mojave that were available +in their SDK, requiring a change to the include paths used when compiling the +CA bindings. The new version should build on new and older macOS versions, and +these changes may also help other targets that have an incomplete installation +of Perl (the build will continue after printing a warning that the Perl CA +bindings could not be built).

+

Routine epicsTempName() removed from libCom

This routine was a simple wrapper around the C89 function tmpnam()