Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ CA Gateway Release Notes
## 2.1.4 (not released yet)
[View diff](https://github.com/epics-extensions/ca-gateway/compare/R2-1-3-0...master)

* Ehhh...
* Support for pcre2 added
* Fix some compiler warnings
* Ensure that ASL defaults to 1

## 2.1.3 (15 Dec 2021)
[View diff](https://github.com/epics-extensions/ca-gateway/compare/R2-1-2-0...R2-1-3-0)
Expand Down
11 changes: 4 additions & 7 deletions configure/CONFIG_SITE
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,20 @@
#######################################################################

# Use Perl compatible regular expressions (PCRE) instead of basic regex
#USE_PCRE=YES

# For PCRE on Linux
# requires package pcre-devel (or libpcre3-dev) for compiling
# requires package pcre (or libpcre3) for running the Gateway
#USE_PCRE=2

# For PCRE on Linux make sure PCRE 1 or 2 deveopment packeges are installed.
ifeq ($(OS_CLASS),WIN32)

# For PCRE on Windows
# For PCRE 1 on Windows
# install libraries and includes from
# https://sourceforge.net/projects/gnuwin32/files/pcre/7.0/pcre-7.0.exe/download
# and set the install location here
PCRE_DIR=C:/Pcre

# For REGEX on Windows
# compile gnuregex inside an EPICS support module from the sources at
# http://www.aps.anl.gov/epics/download/extensions/gnuregex0_13.tar.gz
# https://epics.anl.gov/download/extensions/gnuregex0_13.tar.gz
# and set the module location here
REGEX_DIR=C:/epics/modules/regex

Expand Down
16 changes: 10 additions & 6 deletions docs/Gateway.html
Original file line number Diff line number Diff line change
Expand Up @@ -625,12 +625,16 @@ <h2><a name="AccessSecurity">Access Security</a></h2>
what process variable name patterns are allowed or denied and to optionally
associate patterns with access security groups and security levels in the
access file. The patterns are either Perl compatible regular expressions
(PCRE) or GNU-style regular expressions, depending on the USE_PCRE variable
in Makefile. (See a UNIX book for more information about regular expressions.)
In addition, inverted regular experessions (starting with !) are supported
depending on the USE_NEG_REGEXP variable in Makefile. For compatibility
with earlier versions of the gateway, PCRE and inverted regular expressions
are disable by default. There is a sample file,
(PCRE or PCRE2) or GNU-style regular expressions, depending on the
<code>USE_PCRE</code> variable defined in CONFIG_SITE.
Set <code>USE_PCRE=1</code> (or for backward compatibility
<code>USE_PCRE=YES</code>) to use obsolete PCRE version 1 or set
<code>USE_PCRE=2</code> to use modern PCRE2.

<p>In addition, inverted regular experessions (starting with <code>!</code>)
are supported depending on the <code>USE_NEG_REGEXP</code> variable in Makefile.
For compatibility with earlier versions of the gateway, PCRE and inverted
regular expressions are disable by default. There is a sample file,
gateway.pvlist, in the source distribution and reproduced <a
href="GATEWAY.pvlist">here</a> to get you started. The version in the
distribution may be more recent. Directions for this file are in the sample
Expand Down
6 changes: 3 additions & 3 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ ifeq ($(CMPLR_CLASS),msvc)
USR_LDFLAGS_WIN32 += /SUBSYSTEM:CONSOLE
endif

ifeq ($(USE_PCRE),YES)
USR_CXXFLAGS += -DUSE_PCRE
ifneq ($(filter YES 1 2,$(USE_PCRE)),)
gateAs_CPPFLAGS += -DUSE_PCRE=$(patsubst YES,1,$(USE_PCRE))
ifeq ($(OS_CLASS),WIN32)
ifneq (,$(wildcard $(PCRE_DIR)/inc/*.h))
# Legacy nonstandard pcre3 download and manual install
Expand All @@ -53,7 +53,7 @@ ifeq ($(USE_PCRE),YES)
endif
endif
else
USR_SYS_LIBS += pcre
USR_SYS_LIBS += $(if $(filter 2,$(USE_PCRE)), pcre2-8, pcre)
endif
else
# On Linux basic regex is part of libc
Expand Down
100 changes: 69 additions & 31 deletions src/gateAs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,13 @@ gateAsEntry::gateAsEntry(const char* pattern, const char* realname, const char*
{
#ifdef USE_PCRE
pat_buff = NULL;
#if USE_PCRE == 1
ovector = NULL;
ovecsize = 0;
#endif
#if USE_PCRE == 2
match_data = NULL;
#endif
#else
// Set pointers in the pattern buffer
pat_buff.buffer=NULL;
Expand All @@ -99,8 +104,14 @@ gateAsEntry::~gateAsEntry(void)
{
// Free allocated stuff in the pattern buffer
#ifdef USE_PCRE
#if USE_PCRE == 1
pcre_free(pat_buff);
pcre_free(ovector);
#endif
#if USE_PCRE == 2
pcre2_code_free(pat_buff);
pcre2_match_data_free(match_data);
#endif
#else
regfree(&pat_buff);
// Free allocted stuff in registers
Expand All @@ -124,10 +135,11 @@ long gateAsEntry::removeMember(void)
return rc;
}

void gateAsEntry::getRealName(const char* pv, char* rname, int len)
void gateAsEntry::getRealName(const char* pv, char* rname, size_t len)
{
char c;
int in, ir, j, n;
size_t in, ir, j;
int n;

if (alias) { // Build real name from substitution pattern
ir = 0;
Expand All @@ -139,7 +151,7 @@ void gateAsEntry::getRealName(const char* pv, char* rname, int len)
#ifdef USE_PCRE
if(n < substrings && ovector[2*n] >= 0) {
for(j=ovector[2*n];
ir<len && j<ovector[2*n+1];
ir<len && j<(size_t)ovector[2*n+1];
j++)
rname[ir++] = pv[j];
if(ir==len) {
Expand All @@ -150,7 +162,7 @@ void gateAsEntry::getRealName(const char* pv, char* rname, int len)
#else
if(regs.start[n] >= 0) {
for(j=regs.start[n];
ir<len && j<regs.end[n];
ir<len && j<(size_t)regs.end[n];
j++)
rname[ir++] = pv[j];
if(ir==len) {
Expand Down Expand Up @@ -212,28 +224,49 @@ aitBool gateAsEntry::compilePattern(int line) {
const char *err;

#ifdef USE_NEG_REGEXP
negate_pattern = (pattern[0] == '!');
if (negate_pattern) pattern++;
negate_pattern = (pattern[0] == '!');
if (negate_pattern) pattern++;
#endif

#ifdef USE_PCRE
#if USE_PCRE == 1
int erroffset;
pat_buff = pcre_compile(pattern, 0, &err, &erroffset, NULL);
if(!pat_buff) {
pat_buff = pcre_compile(pattern, 0, &err, &erroffset, NULL);
if(!pat_buff) {
fprintf(stderr,"Line %d: Error after %d chars in Perl regexp: %s\n",
line, erroffset, err);
fprintf(stderr,"%s\n", pattern);
fprintf(stderr,"%*c\n", erroffset+1, '^');
line, erroffset, err);
fprintf(stderr,"%s\n", pattern);
fprintf(stderr,"%*c\n", erroffset+1, '^');
return aitFalse;
}
pcre_fullinfo(pat_buff, NULL, PCRE_INFO_CAPTURECOUNT, &ovecsize);
ovecsize = (ovecsize+1)*3;
ovector = (int*) pcre_malloc (sizeof(int)*ovecsize);
pcre_fullinfo(pat_buff, NULL, PCRE_INFO_CAPTURECOUNT, &ovecsize);
ovecsize = (ovecsize+1)*3;
ovector = (int*) pcre_malloc (sizeof(int)*ovecsize);
#endif

#if USE_PCRE == 2
int errorcode;
PCRE2_SIZE erroffset;
pat_buff = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroffset, NULL);
if(!pat_buff) {
PCRE2_UCHAR buffer[80];
err = (char*)buffer;
pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
fprintf(stderr,"Line %d: Error after %d chars in Perl regexp: %s\n",
line, (int)erroffset, err);
fprintf(stderr,"%s\n", pattern);
fprintf(stderr,"%*c\n", (int)erroffset+1, '^');
return aitFalse;
}
match_data = pcre2_match_data_create_from_pattern(pat_buff, NULL);
ovector = pcre2_get_ovector_pointer(match_data);
#endif

#else
pat_buff.translate=0; pat_buff.fastmap=0;
pat_buff.allocated=0; pat_buff.buffer=0;

if((err = re_compile_pattern(pattern, (int) strlen(pattern), &pat_buff))) {
if((err = re_compile_pattern(pattern, (int) strlen(pattern), &pat_buff))) {
fprintf(stderr,"Line %d: Error in regexp %s : %s\n", line, pattern, err);
return aitFalse;
}
Expand Down Expand Up @@ -388,17 +421,23 @@ gateAsEntry* gateAs::findEntryInList(const char* pv, gateAsList& list) const
tsSLIter<gateAsEntry> pi = list.firstIter();

while(pi.pointer()) {
int len = (int) strlen(pv);
size_t len = strlen(pv);
#ifdef USE_PCRE
#if USE_PCRE == 1
pi->substrings=pcre_exec(pi->pat_buff, NULL,
pv, len, 0, PCRE_ANCHORED, pi->ovector, 30);
if((pi->substrings>=0 && pi->ovector[1] == len)
pv, len, 0, PCRE_ANCHORED, pi->ovector, pi->ovecsize); // max 10 captures
#endif
#if USE_PCRE == 2
pi->substrings=pcre2_match(pi->pat_buff,
(PCRE2_SPTR)pv, len, 0, PCRE2_ANCHORED, pi->match_data, NULL);
#endif
if((pi->substrings>=0 && (size_t)(pi->ovector[1]) == len)
#ifdef USE_NEG_REGEXP
^ pi->negate_pattern
^ pi->negate_pattern
#endif
) break;
#else
if((re_match(&pi->pat_buff, pv, len, 0, &pi->regs) == len)
if((re_match(&pi->pat_buff, pv, len, 0, &pi->regs) == (regoff_t)len)
#ifdef USE_NEG_REGEXP
^ pi->negate_pattern
#endif
Expand All @@ -411,7 +450,6 @@ gateAsEntry* gateAs::findEntryInList(const char* pv, gateAsList& list) const

int gateAs::readPvList(const char* lfile)
{
int lev;
int line=0;
FILE* fd;
char inbuf[GATE_MAX_PVLIST_LINE_LENGTH];
Expand Down Expand Up @@ -448,15 +486,15 @@ int gateAs::readPvList(const char* lfile)

// Read all PV file lines
while(fgets(inbuf,sizeof(inbuf),fd)) {

int lev=1;

++line;
pattern=rname=hname=NULL;

#ifdef USE_DENYFROM
//All deny from rules with host names will be conveted to ip addresses
strncpy(tempInbuf,inbuf,strlen(inbuf));
tempInbuf[strlen(inbuf)-1]='\0';
strncpy(tempInbuf,inbuf,sizeof(tempInbuf)-1);
tempInbuf[sizeof(tempInbuf)-1]='\0';

if((ptr=strchr(inbuf,'#'))) *ptr='\0'; // Take care of comments

Expand Down Expand Up @@ -495,7 +533,7 @@ int gateAs::readPvList(const char* lfile)
ch=strchr(hostname,':');
if(ch != NULL) hostname[ch-hostname]=0;

strncpy(pIPInput,hostname,strlen(hostname));
strncpy(pIPInput,hostname,sizeof(inbufWithIPs)-1-(inbufWithIPs-pIPInput));
*(pIPInput+strlen(hostname)) = ' ';
pIPInput = pIPInput + strlen(hostname) + 1;
}
Expand All @@ -510,20 +548,20 @@ int gateAs::readPvList(const char* lfile)

}else
{
strncpy(inbufWithIPs,tempInbuf,strlen(tempInbuf));
inbufWithIPs[strlen(tempInbuf)]='\0';
strncpy(inbufWithIPs,tempInbuf,sizeof(inbufWithIPs)-1);
inbufWithIPs[sizeof(inbufWithIPs)-1]='\0';
}

}else
{
strncpy(inbufWithIPs,tempInbuf,strlen(tempInbuf));
inbufWithIPs[strlen(tempInbuf)]='\0';
strncpy(inbufWithIPs,tempInbuf,sizeof(inbufWithIPs)-1);
inbufWithIPs[sizeof(inbufWithIPs)-1]='\0';
}

pl=new gateAsLine(inbufWithIPs,strlen(inbufWithIPs),line_list);
pl=new gateAsLine(inbufWithIPs,line_list);
#else
if((ptr=strchr(inbuf,'#'))) *ptr='\0'; // Take care of comments
pl=new gateAsLine(inbuf,strlen(inbuf),line_list);
pl=new gateAsLine(inbuf,line_list);
#endif
if(!(pattern=strtok(pl->buf," \t\n"))) continue;

Expand Down
27 changes: 21 additions & 6 deletions src/gateAs.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ extern "C" {
#include "aitTypes.h"

#ifdef USE_PCRE

#if USE_PCRE == 1
#include <pcre.h>
#endif

#if USE_PCRE == 2
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#endif

#else

extern "C" {
Expand Down Expand Up @@ -121,18 +130,25 @@ class gateAsEntry : public tsSLNode<gateAsEntry>
#endif
long removeMember(void);

void getRealName(const char* pv, char* real, int len);
void getRealName(const char* pv, char* real, size_t len);

const char* pattern;
const char* alias;
const char* group;
int level;
ASMEMBERPVT asmemberpvt;
#ifdef USE_PCRE
pcre* pat_buff;
int substrings;
#if USE_PCRE == 1
pcre* pat_buff;
int ovecsize;
int *ovector;
#endif
#if USE_PCRE == 2
pcre2_code* pat_buff;
pcre2_match_data* match_data;
PCRE2_SIZE *ovector;
#endif
#else
char pat_valid;
struct re_pattern_buffer pat_buff;
Expand Down Expand Up @@ -192,11 +208,10 @@ class gateAsLine : public tsSLNode<gateAsLine>
{
public:
gateAsLine(void) : buf(NULL) { }
gateAsLine(const char* line, size_t len, tsSLList<gateAsLine>& n) :
buf(new char[len+1])
gateAsLine(const char* line, tsSLList<gateAsLine>& n) :
buf(new char[strlen(line)+1])
{
strncpy(buf,line,len+1);
buf[len] = '\0';
strcpy(buf,line);
n.add(*this);
}
~gateAsLine(void)
Expand Down
Loading
Loading